被这题虐了快两天。。。。。。。。。。。。
找最大的异或值显然用trie。。因为还要支持插入删除修改。。所以就用平衡树套trie。
如果旋转的话,整颗trie都要重新建,所以正常姿势是替罪羊树(虽然只是早建晚建的区别= =)
看了学长的解题报告后才敢用treap= =。。结果就陷入了无尽的调试中TAT..代码能力还是拙计...前前后后改了两天,大概得有8h+吧。。。
具体做法:每个treap的节点上建一颗高度为20的trie(因为数的大小<2^20),在trie中插入treap节点所在子树中的所有数字。
显然trie里面得动态开节点,而且还要垃圾回收。旋转的时候暴力重构trie就好了(注意常数)
垃圾回收千万别调stl的队列TAT。。。会慢一半以上。。自己写个栈就一行。。为何要去亲身感受stl的常数TAT
查询的时候就把在treap里拆成一个个对应的小区间和节点,用数组存着,顺便求出第二大的数值。计算异或值的时候可以一个一个跑,也可以一次在一颗trie上跑完。后一种的话要记得把已经无法匹配的节点丢掉,并且速度也比前一种快一些。。
感觉自己的常数已经没法再压了。。然而跑了倒数第2。。orz
运行了下云神的代码发现自己的删除操作慢了一倍多= =。。。至今原因不明TAT。。而且数据很多都是删除、插入的操作(针对替罪羊树)TAT。。其他操作还不慢。
一开始建treap的时候记得递归建树(最主要的是避免无谓的旋转)。。
代码长度还好。。不到6k。。我是应该高兴还是悲伤呢。。。
话说原来代码可读性这种东西真的是毫无下限的啊。。。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<cstdlib> 6 #include<queue> 7 #define get top?st[top--]:++tt 8 using namespace std; 9 const int maxn=100033<<1; 10 const int maxm=maxn*160; 11 int two[21],len; 12 int ch[2][maxm],sm[maxm],tt;int st[maxm],top; 13 int l[maxn],r[maxn],num[maxn],sz[maxn],mx1[maxn],mx2[maxn],rnd[maxn],rt[maxn],tot,nowmx1,nowmx2; 14 int i,j,n,m,x,y,root,ans,tmp,V; 15 int ra;char rx; 16 inline int read(){ 17 rx=getchar(),ra=0; 18 while(rx<'0'||rx>'9')rx=getchar(); 19 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 20 } 21 inline void ins(int &rt,int v){ 22 if(!rt)rt=get;int x=rt;++sm[x]; 23 for(register int i=19;i>=0;i--) 24 if(v&two[i])++sm[ ch[1][x] ? x=ch[1][x] : x=ch[1][x]=get ];else 25 ++sm[ ch[0][x]?x=ch[0][x]:x=ch[0][x]=get ]; 26 } 27 inline void clr(int &x){ 28 st[++top]=x,sm[x]=0; 29 if(ch[0][x])clr(ch[0][x]);if(ch[1][x])clr(ch[1][x]); 30 x=0; 31 } 32 inline void del(int x,int v){ 33 --sm[x];bool k; 34 for(register int i=19,j=x;i>=0;j=x,i--){ 35 if(v&two[i])x=ch[k=1][j];else x=ch[k=0][j]; 36 if(!(--sm[x])){ch[k][j]=0,clr(x);return;} 37 } 38 } 39 inline void update(int &x,int l,int r){//merge 40 x=get,sm[x]=sm[l]+sm[r]; 41 if(ch[0][l]||ch[0][r])update(ch[0][x],ch[0][l],ch[0][r]); 42 if(ch[1][l]||ch[1][r])update(ch[1][x],ch[1][l],ch[1][r]); 43 } 44 45 inline void upd(int x,int l,int r){ 46 sz[x]=sz[l]+sz[r]+1; 47 if(mx1[l]<mx1[r])mx1[x]=mx1[r],mx2[x]=mx1[l];else mx1[x]=mx1[l],mx2[x]=mx1[r]; 48 if(mx2[l]<mx2[r])if(mx2[x]<mx2[r])mx2[x]=mx2[r];else; 49 else if(mx2[x]<mx2[l])mx2[x]=mx2[l]; 50 if(mx1[x]<num[x])mx2[x]=mx1[x],mx1[x]=num[x];else 51 if(mx2[x]<num[x])mx2[x]=num[x]; 52 } 53 inline void lturn(int &x,int R){ 54 r[x]=l[R],l[R]=x,sz[R]=sz[x],mx1[R]=mx1[x],mx2[R]=mx2[x], 55 clr(rt[R]),rt[R]=rt[x],upd(x,l[x],r[x]),update(rt[x],rt[l[x]],rt[r[x]]),ins(rt[x],num[x]),x=R; 56 } 57 inline void rturn(int &x,int L){ 58 l[x]=r[L],r[L]=x,sz[L]=sz[x],mx1[L]=mx1[x],mx2[L]=mx2[x], 59 clr(rt[L]),rt[L]=rt[x],upd(x,l[x],r[x]),update(rt[x],rt[l[x]],rt[r[x]]),ins(rt[x],num[x]),x=L; 60 } 61 inline void insert(int &x,int po,int v){ 62 if(!x){x=++tot,rnd[x]=(rand()>>1)+tot,num[x]=mx1[x]=v,sz[x]=1,ins(rt[x],v);return;} 63 sz[x]++,ins(rt[x],v); 64 if(v>mx1[x])mx2[x]=mx1[x],mx1[x]=v;else if(v>mx2[x])mx2[x]=v; 65 if(po>sz[l[x]]+1){ 66 insert(r[x],po-sz[l[x]]-1,v); 67 if(rnd[r[x]]<rnd[x])lturn(x,r[x]); 68 }else{ 69 insert(l[x],po,v); 70 if(rnd[l[x]]<rnd[x])rturn(x,l[x]); 71 } 72 } 73 inline void change(int &x,int po,int v){ 74 if(sz[l[x]]+1==po)V=num[x],num[x]=v;else 75 if(po<=sz[l[x]])change(l[x],po,v); 76 else change(r[x],po-sz[l[x]]-1,v); 77 del(rt[x],V),ins(rt[x],v),upd(x,l[x],r[x]); 78 } 79 inline void delet(int &x,int po){ 80 if(sz[l[x]]+1==po){ 81 if(!(l[x]&&r[x]))V=num[x],clr(rt[x]),x=l[x]|r[x];else 82 if(rnd[l[x]]<rnd[r[x]])rturn(x,l[x]),delet(x,po); 83 else lturn(x,r[x]),delet(x,po); 84 }else if(po<=sz[l[x]])delet(l[x],po),upd(x,l[x],r[x]),del(rt[x],V); 85 else delet(r[x],po-sz[l[x]]-1),upd(x,l[x],r[x]),del(rt[x],V); 86 } 87 int st1[maxn],st2[maxn],top1,top2; 88 inline void getmx(int x,int L,int R){ 89 if(L==1&&R==sz[x]){ 90 st1[++top1]=rt[x]; 91 if(mx1[x]>nowmx1)nowmx2=nowmx1,nowmx1=mx1[x];else if(mx1[x]>nowmx2)nowmx2=mx1[x]; 92 if(mx2[x]>nowmx2)nowmx2=mx2[x]; 93 return; 94 } 95 if(L>sz[l[x]]+1)getmx(r[x],L-sz[l[x]]-1,R-sz[l[x]]-1); 96 else if(R<=sz[l[x]])getmx(l[x],L,R); 97 else{ 98 if(num[x]>nowmx1)nowmx2=nowmx1,nowmx1=num[x];else if(num[x]>nowmx2)nowmx2=num[x]; 99 st2[++top2]=num[x]; 100 if(L<=sz[l[x]])getmx(l[x],L,sz[l[x]]);if(R>sz[l[x]]+1)getmx(r[x],1,R-sz[l[x]]-1); 101 } 102 } 103 inline int query(int l,int r){ 104 nowmx1=nowmx2=top1=top2=0,getmx(root,l,r); 105 register int i,j,tmp;int ans=0,now=0;bool k,flag; 106 for(;top2;top2--)if((nowmx2^st2[top2])>ans)ans=nowmx2^st2[top2]; 107 for(i=19;i>=0&&top1&&(now+two[i+1]-1>ans);--i){ 108 for(k=!(nowmx2&two[i]),j=top1,flag=0;j;--j)if(ch[k][st1[j]]){flag=1;break;} 109 for(j=1,tmp=top1,top1=0,now+=flag?two[i]:0,k^=!flag;j<=tmp;++j)if(ch[k][st1[j]])st1[++top1]=ch[k][st1[j]]; 110 } 111 return now<ans?ans:now; 112 } 113 inline void build(int L,int R,int &x,int fa){ 114 if(L>R)return; 115 x=(L+R)>>1;tot++; 116 if(L<R)build(L,x-1,l[x],x),num[x]=read(),build(x+1,R,r[x],x),upd(x,l[x],r[x]),update(rt[x],rt[l[x]],rt[r[x]]),ins(rt[x],num[x]); 117 else mx1[x]=num[x]=read(),sz[x]=1,ins(rt[x],num[x]); 118 rnd[x]=rnd[fa]+rand()&23; 119 } 120 121 char s[15];int LEN; 122 inline void outx(int x){ 123 if(!x){puts("0");return;} 124 while(x)s[LEN++]=x%10,x/=10; 125 while(LEN)putchar(s[--LEN]+48);putchar(' '); 126 } 127 int main(){ 128 for(i=0;i<=20;i++)two[i]=1<<i; 129 n=read(),m=read();char id; 130 build(1,n,root,0); 131 while(m--){ 132 for(id=getchar();id<'A'||id>'Z';id=getchar()); 133 x=read()+ans;if(x>=sz[root])x%=sz[root]; 134 if(id!='D'){ 135 y=read()+ans; 136 if(id!='F')if(y>=1048576)y%=1048576;else; 137 else if(y>=sz[root])y%=sz[root]; 138 } 139 x++;if(id=='F')y++; 140 if(id=='I')insert(root,x,y); 141 if(id=='D')delet(root,x); 142 if(id=='C')change(root,x,y); 143 if(id=='F'){if(x>y)swap(x,y);ans=query(x,y),outx(ans);} 144 } 145 return 0; 146 }