题目大意:带插入、修改的区间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;
}