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