[模板] 普通平衡樹
阿新 • • 發佈:2018-11-28
您需要一種資料結構:
- 插入一個數\(x\)
- 刪除一個數\(x\)
- 查詢\(x\)這個數在所有數中的排名
- 查詢排名為\(x\)的數
- 求\(x\)這個數的前驅(前驅定義為小於\(x\)的最大數)‘
- 求\(x\)這個數的後繼(後繼定義為大於\(x\)的最小數)
平衡樹
- 不會
樹狀陣列
- 不會
線段樹
不會- 先離散化一下,因為數字太大了
- 線段樹維護區間內有多少個數
- 離散化的新編號就是線段樹對應區間的位置
插入ins()
- 計算\(x\)離散化後的對應編號\(num\)
- 單點修改區間\([num,num]\)
刪除del()
- 計算\(x\)離散化後的對應編號\(num\)
- 單點修改區間\([num,num]\),-1即可
查詢排名clac_rk()
- 計算\(x\)離散化後的對應編號\(num\)
- 查詢區間\([1,num]\)的和,+1即是答案,因為\(x\)前面有若干個數,若干個數+1就\(x\)的排名
查詢對應排名的數find_rk()
- 二分查詢,判斷\([1,mid]\)的和與給定排名的大小關係。
查前驅
find_rk(calc_rk(x)-1)
查後繼
find_rk(calc_rk(x)+N+1)
,其中\(N\)
程式碼
#include <cstdio> #include <cstring> #include <algorithm> #define MAXN 100005 #define lson (rt<<1) #define rson (rt<<1|1) int seg[MAXN<<2]; inline void pushup(int rt) { seg[rt] = seg[lson] + seg[rson]; } void update(int C,int L,int rt,int l,int r) { if(l==r&&l==L) { seg[rt] += C; return; } int mid = (l+r)>>1; if(L<=mid) update(C,L,lson,l,mid); else update(C,L,rson,mid+1,r); pushup(rt); } int query(int L,int R,int rt,int l,int r) { if(L>R) return 0; if(L<=l&&R>=r) return seg[rt]; if(L>r||R<l) return 0; int mid = (l+r)>>1,ans = 0; if(L<=mid) ans += query(L,R,lson,l,mid); if(R>mid) ans += query(L,R,rson,mid+1,r); return ans; } struct Discretization { int temp[MAXN],num[MAXN],tot,cnt; void reset() { tot = 0; cnt = 0; } int get_num(int u) { int l = 1, r = tot; while(l<r) { int mid = (l+r+1)>>1; if(num[mid]>u) r = mid - 1; else l = mid; } return l; } int find(int rk) { int l = 1,r = tot; while(l<r) { int mid = (l+r)>>1; int x = query(1,mid,1,1,tot); if(x>=rk) r = mid; else l = mid + 1; } return num[l]; } void add(int u) { temp[++cnt] = u; } void unique() { for(int i=1;i<=cnt;++i) { if(temp[i]!=temp[i+1]) num[++tot] = temp[i]; } } }D; struct Opt { int opt,num; }G[MAXN]; int N; int main() { D.reset(); scanf("%d",&N); for(int i=1;i<=N;++i) { scanf("%d%d",&G[i].opt,&G[i].num); if(G[i].opt!=4) D.add(G[i].num); } std::sort(D.temp+1,D.temp+1+D.cnt); D.unique(); std::memset(seg,0,sizeof(seg)); for(int i=1;i<=N;++i) { if(G[i].opt==1) update(1,D.get_num(G[i].num),1,1,D.tot); else if(G[i].opt==2) update(-1,D.get_num(G[i].num),1,1,D.tot); else if(G[i].opt==3) printf("%d\n",query(1,D.get_num(G[i].num)-1,1,1,D.tot) + 1); else if(G[i].opt==4) printf("%d\n",D.find(G[i].num)); else if(G[i].opt==5) { int rk = query(1,D.get_num(G[i].num)-1,1,1,D.tot); printf("%d\n",D.find(rk)); } else if(G[i].opt==6) { int x = D.get_num(G[i].num); int rk = query(1,x-1,1,1,D.tot) + query(x,x,1,1,D.tot) + 1; printf("%d\n",D.find(rk)); } } return 0; }