题目大意:带插入、修改的区间k小值
我也作死去学了下替罪羊树(OTZ HZWER)……之前在想平衡树套不了线段树看到这题直接秒收弗拉格啊
普通的平衡树由于有旋转操作 所以如果每旋转一次都重建一次平衡树妥妥TLE 但是替罪羊树就没什么问题 因为替罪羊树没有旋转
如果一个节点的某个儿子的size超过了本身size的55%~80% 就暴力重建这棵子树 这个节点就被称作替罪羊节点
个人对“替罪羊”的理解就是“明明是我的儿子过大为什么要把我重建啊QAQ”啥的……
于是我们每次插入时都把所有需要重建的替罪羊节点压到一个栈里 然后取深度最小的那个进行重建
无视代码里那变态的封装吧…… 记得写垃圾回收不然会挂
各种封装各种重载new重载delete啥的各种写不明白搞了一下午……最后交上去1A我也是醉了……HZWER究竟为何能写的那么短……
最后虽然出题人让我们自行nlog^2n但是我还是作死写了nlog^3n……懒得改了
#include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 70700 #define ALPHA 0.8 using namespace std; struct Segtree{ Segtree *ls,*rs; int num; void* operator new (size_t size); void operator delete (void* p); void Insert(int x,int y,int val); void Delete(int x,int y,int val); int Get_Ans(int x,int y,int val); void Decomposition(); }*mempool,*C; struct abcd{ abcd *ls,*rs; int num,size; Segtree* tree; void* operator new (size_t size,int x); void operator delete (void *p); void Maintain(); void Decomposition(); bool Check(); }*root,*_mempool,*G; queue<void*>bin[2]; int n,m,ans,a[M],tot; abcd **stack[M];int top; int changed_num; void* Segtree :: operator new (size_t size) { if( !bin[0].empty() ) { void *re=bin[0].front(); bin[0].pop(); memset(re,0,sizeof(Segtree) ); return re; } if(C==mempool) { C=new Segtree[1<<15]; mempool=C+(1<<15); memset(C,0,sizeof(Segtree)*(1<<15) ); } return C++; } void Segtree :: operator delete (void *p) { bin[0].push(p); } void Segtree :: Insert(int x,int y,int val) { int mid=(x+y)>>1; num++; if(x==y) return ; if(val<=mid) { if(!ls) ls=new Segtree; ls->Insert(x,mid,val); } else { if(!rs) rs=new Segtree; rs->Insert(mid+1,y,val); } } void Segtree :: Delete(int x,int y,int val) { int mid=(x+y)>>1; num--; if(x==y) return ; if(val<=mid) ls->Delete(x,mid,val); else rs->Delete(mid+1,y,val); } int Segtree :: Get_Ans(int x,int y,int val) { int mid=(x+y)>>1; if(!num) return 0; if(x==y) return num; if(val<=mid) return ls?ls->Get_Ans(x,mid,val):0; else return (ls?ls->num:0) + (rs?rs->Get_Ans(mid+1,y,val):0); } void Segtree :: Decomposition() { if(ls) ls->Decomposition(); if(rs) rs->Decomposition(); delete this; } void* abcd :: operator new (size_t size,int x) { if( !bin[1].empty() ) { abcd *re=(abcd*)bin[1].front(); bin[1].pop(); re->ls=re->rs=0x0; re->num=x;re->size=1; re->tree=new Segtree; return re; } if(G==_mempool) { G=new abcd[1<<15]; _mempool=G+(1<<15); memset(G,0,sizeof(abcd)*(1<<15) ); } G->ls=G->rs=0x0; G->num=x;G->size=1; G->tree=new Segtree; return G++; } void abcd :: operator delete (void *p) { bin[1].push(p); } void abcd :: Maintain() { size=1; if(ls) size+=ls->size; if(rs) size+=rs->size; } void abcd :: Decomposition() { if(ls) ls->Decomposition(); a[++tot]=num; if(rs) rs->Decomposition(); tree->Decomposition(); delete this; } abcd* Build_Tree(int x,int y) { int i; if(x>y) return 0x0; int mid=(x+y)>>1; abcd *re=new (a[mid]) abcd; re->ls=Build_Tree(x,mid-1); re->rs=Build_Tree(mid+1,y); for(i=x;i<=y;i++) re->tree->Insert(0,70000,a[i]); return re->Maintain(),re; } void Rebuild(abcd *&x) { top=0;tot=0; x->Decomposition(); x=Build_Tree(1,tot); } bool abcd :: Check() { static double rate; if(ls) { rate=ls->size*1.0/size; if(rate>ALPHA) return true; } if(rs) { rate=rs->size*1.0/size; if(rate>ALPHA) return true; } return false; } void Insert(abcd *&x,int y,int z) { if(!x) { x=new (z) abcd; x->tree->Insert(0,70000,z); return; } x->tree->Insert(0,70000,z); int temp=x->ls?x->ls->size:0; if(y<=temp) { Insert(x->ls,y,z); if( x->ls->Check() ) stack[++top]=&x->ls; } else { Insert( x->rs,y-temp-1,z ); if( x->rs->Check() ) stack[++top]=&x->rs; } x->Maintain(); } int Get_Lesser(abcd *x,int y,int z) { int re=0,temp=x->ls?x->ls->size:0; if(!y) return 0; if(y<=temp) return Get_Lesser(x->ls,y,z); y-=temp; if(x->ls) re+=x->ls->tree->Get_Ans(0,70000,z); y--;re+=(x->num<=z); if(!y) return re; return re + Get_Lesser(x->rs,y,z); } int Query(int x,int y,int k) { int l=0,r=70000; while(l+1<r) { int mid=(l+r)>>1; if( Get_Lesser(root,y,mid)- Get_Lesser(root,x-1,mid)>=k ) r=mid; else l=mid; } if( Get_Lesser(root,y,l)- Get_Lesser(root,x-1,l)>=k ) return l; return r; } void Modify(abcd *x,int y,int z) { int temp=x->ls?x->ls->size:0; if(y<=temp) Modify(x->ls,y,z); else if((y-=temp)==1) changed_num=x->num,x->num=z; else Modify(x->rs,--y,z); x->tree->Delete(0,70000,changed_num); x->tree->Insert(0,70000,z); } void Insert(int x,int y) { --x;++n; Insert(root,x,y); if( root->Check() ) stack[++top]=&root; if(top) Rebuild(*stack[top]); } void Output(abcd *x) { if(!x) return; Output(x->ls); printf("======%d\n",x->num); Output(x->rs); } int main() { int i,x,y,k; char p[10]; cin>>n; for(i=1;i<=n;i++) scanf("%d",&a[i]); root=Build_Tree(1,n); cin>>m; for(i=1;i<=m;i++) { //Output(root); scanf("%s%d%d",p,&x,&y); x^=ans;y^=ans; switch(p[0]) { case 'Q': scanf("%d",&k);k^=ans; printf("%d\n",ans=Query(x,y,k) ); break; case 'M': Modify(root,x,y); break; case 'I': Insert(x,y); break; } } return 0; }