權值線段樹 動態開點

2022-01-30 11:19:42 字數 1710 閱讀 3116

普通平衡樹

題目給的資料是1e-7到1e7,直接寫線段樹記憶體肯定是比較吃力,而且題目還要維護rank和第k大,這時候就用到動態開點了,因為運算元一共就1e5,所以最多也只需要開\(log_2(2e7)\)大小的陣列。

修改函式

void add(int &rt, int l, int r, int x, int v) ,-1則該節點的size--,+1則該節點size++

if (l == r)

return; //建點到目標位置,結束

int mid = (l + r) >> 1;

if (x <= mid) add(ls[rt], l, mid, x, v);//在左邊

else add(rs[rt], mid + 1, r, x, v);//在右邊

}

主函式中
if (op == 1) 

if (op == 2)

即為x前面存在的節點個數加一

查詢函式

int getnum(int rt, int l, int r, int x) 

int mid = (l + r) >> 1;

if (x <= mid)

return getnum(ls[rt], l, mid, x); //直接在左邊節點跑就ok

return size[ls[rt]] + getnum(rs[rt], mid + 1, r, x); //左側的節點數目加上右側x前的數目

}

主函式中
if (op == 3)
對當前的k值與左區間的size比較

查詢函式

int getk(int rt, int l, int r, int k)
主函式
if (op == 4)
if (op == 5) 

if (op == 6)

#include using namespace std;

const int maxn = 1e5 + 10;

const int logm = 30;

int root;

int nodecnt;

int ls[maxn * logm], rs[maxn * logm], size[maxn * logm];

void add(int &rt, int l, int r, int x, int v)

int getnum(int rt, int l, int r, int x)

int mid = (l + r) >> 1;

if (x <= mid)

return getnum(ls[rt], l, mid, x);//直接在左邊節點跑就ok

return size[ls[rt]] + getnum(rs[rt], mid + 1, r, x);//左側的節點數目加上右側x前的數目

}int getk(int rt, int l, int r, int k)

int main()

if (op == 2)

if (op == 3)

if (op == 4)

if (op == 5)

if (op == 6)

}return 0;

}

權值線段樹 動態開點(學習小結)

include include define fo i,a,b for int i a i b i const int n 200050 using namespace std int t n 18 ls n 18 rs n 18 x,now,add,tot int tag n 18 int n,n...

線段樹動態開點

為了降低權值線段樹的空間複雜度,可以不直接建出整棵線段樹的結構,而是在最初只建立乙個根節點,當需要訪問某棵為建立的子樹的時候,再建立代表這個子樹的節點。動態開點的線段樹用變數記錄左右節點的編號。值域為1 n的動態開點線段樹在m次單點修改後,節點規模為o mlogn 例題 p1908 逆序對 這題n最...

線段樹 動態開點

在一些計數問題中,線段樹用於維護值域 一段權值範圍 這樣的線段樹也稱為權值線段樹。為了降低空間複雜度,我們可以不建出整棵線段樹的結構,而是在最初只建立乙個根節點,代表整個區間,當需要訪問線段樹的某棵子樹 某個子區間 時,再建立代表這個子區間的節點。採用這種方法維護的線段樹稱為動態開點的線段樹。動態開...