用樹狀數組實現的平衡樹
阿新 • • 發佈:2018-10-06
前綴和 ret pac 題目 con 前驅 ble -- val
一、題目:
洛谷模板
二、思路:
用樹狀數組實現的平衡樹,實現起來很簡單,但有很多細節需要考慮。
維護一個權值樹狀數組,查排名時直接前綴和,前驅、後繼都很簡單。比較難的是已知排名求值,需要倍增。
怎麽能寫二分呢?倍增比二分快幾百倍。——LSH
需要離散化,而細節很多,具體看代碼。
三、代碼:
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; inline int read(void){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return f*x; } const int maxn=100005; int n,b[maxn],cnt; struct Opt{ int opt,x; }q[maxn]; struct BIT{ int tree[maxn]; inline int lowbit(int x){return x&(-x);} inline void add(int p,int x){ while(p<=cnt){ tree[p]+=x; p+=lowbit(p); } } inline int rank(int p){ int ans=1;--p; while(p>0){ ans+=tree[p]; p-=lowbit(p); } return ans; } inline int val(int rank){ int ans=0,Cnt=0; for(register int i=20;i>=0;--i){ ans+=(1<<i); if(ans>cnt||Cnt+tree[ans]>=rank)ans-=(1<<i); else Cnt+=tree[ans]; } return ++ans; } inline int pre(int x){ return val(rank(x)-1); } inline int nxt(int x){ return val(rank(x+1)); } }T; int main(){ n=read(); for(register int i=1;i<=n;++i){ q[i].opt=read(); q[i].x=read(); if(q[i].opt!=4)b[++cnt]=q[i].x; } sort(b+1,b+cnt+1); cnt=unique(b+1,b+cnt+1)-b-1; for(register int i=1;i<=n;++i){ if(q[i].opt!=4)q[i].x=lower_bound(b+1,b+cnt+1,q[i].x)-b; } for(register int i=1;i<=n;++i){ switch(q[i].opt){ case 1: T.add(q[i].x,1); break; case 2: T.add(q[i].x,-1); break; case 3: cout<<T.rank(q[i].x)<<endl; break; case 4: // T.add(q[i].x,1); cout<<b[T.val(q[i].x)]<<endl; // T.add(q[i].x,-1); break; case 5: T.add(q[i].x,1); cout<<b[T.pre(q[i].x)]<<endl; T.add(q[i].x,-1); break; case 6: T.add(q[i].x,1); cout<<b[T.nxt(q[i].x)]<<endl; T.add(q[i].x,-1); break; } } system("pause"); return 0; }
用樹狀數組實現的平衡樹