用这两道题学了下Splay,也加深了对其的理解。
平衡树的标记与线段树的标记不同,在平衡树中,所有被访问的节点一定不能有标记;否则将其Splay后就找不到其原先的左右子树了。
代码(数据结构1):
#include<cstdlib> #include<cstdio> #include<cstring> #include<vector> using namespace std; #include<iostream> #include<cmath> struct SS{ <span style="white-space:pre"> </span>SS * f,* c[2]; <span style="white-space:pre"> </span>int X,data,delta; <span style="white-space:pre"> </span>bool is_root; }*null=new SS((SS){null,null,null,0,0,0,0}),*root; inline void zig(SS * x,bool D){ <span style="white-space:pre"> </span>SS * ftr=x->f; <span style="white-space:pre"> </span>if(ftr->is_root)x->is_root=1,ftr->is_root=0; <span style="white-space:pre"> </span>x->f=ftr->f; <span style="white-space:pre"> </span>if(x->f->c[0]==ftr)x->f->c[0]=x; <span style="white-space:pre"> </span>else x->f->c[1]=x; <span style="white-space:pre"> </span>ftr->c[D]=x->c[!D]; <span style="white-space:pre"> </span>ftr->c[D]->f=ftr; <span style="white-space:pre"> </span>x->c[!D]=ftr; <span style="white-space:pre"> </span>ftr->f=x; } inline void splay(SS * x){ <span style="white-space:pre"> </span>bool D; <span style="white-space:pre"> </span>//cout<<"S:("<<x->data<<")"<<x->X<<"->"<<x->c[0]->data<<"->"<<x->c[1]->data<<endl; <span style="white-space:pre"> </span>while(!x->is_root){ <span style="white-space:pre"> </span>D=x->f->c[1]==x; <span style="white-space:pre"> </span>if(!x->f->is_root&&D==(x->f->f->c[1]==x->f))zig(x->f,D); <span style="white-space:pre"> </span>zig(x,D); <span style="white-space:pre"> </span>//cout<<D<<"S:("<<x->data<<")"<<x->X<<"->"<<x->c[0]->data<<"->"<<x->c[1]->data<<endl; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>root=x; <span style="white-space:pre"> </span>//cout<<"S:("<<x->data<<")"<<x->X<<"->"<<x->c[0]->data<<"->"<<x->c[1]->data<<endl; } inline void paint(SS * x,int A){ <span style="white-space:pre"> </span>if(x==null)return; <span style="white-space:pre"> </span>x->X+=A; <span style="white-space:pre"> </span>x->delta+=A; } inline void pushdown(SS * x){ <span style="white-space:pre"> </span>if(x->delta){ <span style="white-space:pre"> </span>paint(x->c[0],x->delta); <span style="white-space:pre"> </span>paint(x->c[1],x->delta); <span style="white-space:pre"> </span>x->delta=0; <span style="white-space:pre"> </span>} } inline SS * find(SS * x,int A){ <span style="white-space:pre"> </span>pushdown(x); <span style="white-space:pre"> </span>//cout<<"To "<<A<<" Find:("<<x->data<<")"<<x->X<<"->"<<x->c[0]->data<<"->"<<x->c[1]->data<<endl; <span style="white-space:pre"> </span>if(A==x->X)return x; <span style="white-space:pre"> </span>if(A>x->X)return find(x->c[1],A); <span style="white-space:pre"> </span>return find(x->c[0],A); } int N; inline void prt(SS * x){ <span style="white-space:pre"> </span>if(x==null)return; <span style="white-space:pre"> </span>pushdown(x); <span style="white-space:pre"> </span>prt(x->c[0]); <span style="white-space:pre"> </span>if(x->X<=N)printf("%d ",x->data); <span style="white-space:pre"> </span>prt(x->c[1]); } char * ptr=(char *)malloc(5000000); inline int in(){ <span style="white-space:pre"> </span>bool flag=0; <span style="white-space:pre"> </span>while(*ptr<'0'||*ptr>'9') <span style="white-space:pre"> </span>if(*ptr++=='-') <span style="white-space:pre"> </span>flag=1; <span style="white-space:pre"> </span>int x=0; <span style="white-space:pre"> </span>while(*ptr>47&&*ptr<58)x=x*10+*ptr++-'0'; <span style="white-space:pre"> </span>if(flag)return -x; <span style="white-space:pre"> </span>return x; } int main(){ <span style="white-space:pre"> </span>freopen("codevs2047.in","r",stdin); <span style="white-space:pre"> </span>fread(ptr,1,5000000,stdin); <span style="white-space:pre"> </span>int M,X; <span style="white-space:pre"> </span>N=in(),M=in(); <span style="white-space:pre"> </span>root=new SS((SS){null,null,null,1,in(),0,1}); <span style="white-space:pre"> </span>SS * tmp=root; <span style="white-space:pre"> </span>for(int i=2;i<=N;++i){ <span style="white-space:pre"> </span>tmp->c[1]=new SS((SS){tmp,null,null,i,in(),0,0}); <span style="white-space:pre"> </span>tmp=tmp->c[1]; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>tmp->c[1]=new SS((SS){tmp,null,null,N+1,N+1,0,0}); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>int L,R; <span style="white-space:pre"> </span>while(M--){ <span style="white-space:pre"> </span>L=in(),R=in(); <span style="white-space:pre"> </span>if(--L){ <span style="white-space:pre"> </span>splay(find(root,L)); <span style="white-space:pre"> </span>root->c[1]->is_root=1; <span style="white-space:pre"> </span>splay(find(root->c[1],R+1)); <span style="white-space:pre"> </span>root->is_root=0; <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>tmp=root->c[0]; <span style="white-space:pre"> </span>root->c[0]=null; <span style="white-space:pre"> </span>root=root->f; <span style="white-space:pre"> </span>root->X+=R-L; <span style="white-space:pre"> </span>paint(root->c[0],R-L); <span style="white-space:pre"> </span>splay(find(root,R-L+1)); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>tmp->f=root; <span style="white-space:pre"> </span>root->c[0]=tmp; <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>paint(tmp,-L); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>prt(root); }
#include<iostream> using namespace std; #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> char * ptr=(char *)malloc(5000000); inline int in(){ <span style="white-space:pre"> </span>bool flag=0; <span style="white-space:pre"> </span>while(*ptr<'0'||*ptr>'9') <span style="white-space:pre"> </span>if(*++ptr=='-') <span style="white-space:pre"> </span>flag=1; <span style="white-space:pre"> </span>int x=0; <span style="white-space:pre"> </span>while(*ptr>47&&*ptr<58)x=x*10+*ptr++-'0'; <span style="white-space:pre"> </span>if(flag)return -x; <span style="white-space:pre"> </span>else return x; } struct SS{ <span style="white-space:pre"> </span>SS * f,* c[2]; <span style="white-space:pre"> </span>int key,X; <span style="white-space:pre"> </span>bool is_root; <span style="white-space:pre"> </span>int flagb,flagc; }* null=new SS((SS){null,null,null,-1,-1,0,0,0}),* root=new SS((SS){null,null,null,-0x7f,0,1,1,0}); inline void zig(SS * x,bool w){ <span style="white-space:pre"> </span>SS * ftr=x->f; <span style="white-space:pre"> </span>x->f=ftr->f; <span style="white-space:pre"> </span>if(ftr->is_root)ftr->is_root=0,x->is_root=1; <span style="white-space:pre"> </span>if(x->f->c[0]==ftr)x->f->c[0]=x; <span style="white-space:pre"> </span>else x->f->c[1]=x; <span style="white-space:pre"> </span>ftr->c[w]=x->c[!w]; <span style="white-space:pre"> </span>ftr->c[w]->f=ftr; <span style="white-space:pre"> </span>x->c[!w]=ftr; <span style="white-space:pre"> </span>ftr->f=x; } inline void splay(SS * x){ <span style="white-space:pre"> </span>bool w; <span style="white-space:pre"> </span>while(!x->is_root){ <span style="white-space:pre"> </span>w=x->f->c[1]==x; <span style="white-space:pre"> </span>if(!x->f->is_root&&w==(x->f->f->c[1]==x->f))zig(x->f,w); <span style="white-space:pre"> </span>zig(x,w); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>root=x; } #define Re(x) x=-x; inline void paint(SS * x,int b,int c){ <span style="white-space:pre"> </span>if(x==null)return; <span style="white-space:pre"> </span>int tmp=x->X; <span style="white-space:pre"> </span>if(b-1){ <span style="white-space:pre"> </span>Re(x->flagb); <span style="white-space:pre"> </span>Re(x->flagc); <span style="white-space:pre"> </span>Re(x->X); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>x->flagc+=c; <span style="white-space:pre"> </span>x->X+=c; <span style="white-space:pre"> </span>//cout<<"Paint("<<x->key<<"):"<<tmp<<"->"<<x->X<<"("<<x->flagb<<")\n"; } inline void pushdown(SS * x){ <span style="white-space:pre"> </span>if(x->flagb-1|x->flagc){ <span style="white-space:pre"> </span>if(x->flagb-1)swap(x->c[0],x->c[1]); <span style="white-space:pre"> </span>paint(x->c[0],x->flagb,x->flagc); <span style="white-space:pre"> </span>paint(x->c[1],x->flagb,x->flagc); <span style="white-space:pre"> </span>x->flagb=1; <span style="white-space:pre"> </span>x->flagc=0; <span style="white-space:pre"> </span>} } inline SS * find(int A){ <span style="white-space:pre"> </span>SS * x=root; <span style="white-space:pre"> </span>//cout<<"Find:"<<x->key<<"("<<x->X<<"),"<<A<<"("<<x->flagb<<")"<<"->"<<x->c[0]->key<<"->"<<x->c[1]->key<<endl; <span style="white-space:pre"> </span>while(x->X!=A){ <span style="white-space:pre"> </span>pushdown(x); <span style="white-space:pre"> </span>if(x->X<A)x=x->c[1]; <span style="white-space:pre"> </span>else x=x->c[0]; <span style="white-space:pre"> </span>//cout<<"Find:"<<x->key<<"("<<x->X<<"),"<<A<<"("<<x->flagb<<")"<<"->"<<x->c[0]->key<<"->"<<x->c[1]->key<<endl; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>pushdown(x); <span style="white-space:pre"> </span>return x; } int N; inline void prt(SS * x){ <span style="white-space:pre"> </span>if(x!=null){ <span style="white-space:pre"> </span>pushdown(x); <span style="white-space:pre"> </span>prt(x->c[0]); <span style="white-space:pre"> </span>if(x->X&&x->X<=N)printf("%d ",x->key); <span style="white-space:pre"> </span>prt(x->c[1]); <span style="white-space:pre"> </span>} } int main(){ <span style="white-space:pre"> </span>freopen("codevs2048.in","r",stdin); <span style="white-space:pre"> </span>fread(ptr,1,5000000,stdin); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>N=in(); <span style="white-space:pre"> </span>int M=in(),i; <span style="white-space:pre"> </span>SS * tmp=root; <span style="white-space:pre"> </span>for(i=1;i<=N;++i){ <span style="white-space:pre"> </span>tmp->c[1]=new SS((SS){tmp,null,null,in(),i,0,1,0}); <span style="white-space:pre"> </span>tmp=tmp->c[1]; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>tmp->c[1]=new SS((SS){tmp,null,null,0x7f,N+1,0,1,0}); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>int l,r; <span style="white-space:pre"> </span>while(M--){ <span style="white-space:pre"> </span>//cout<<"--------"<<M<<"-------\n"; <span style="white-space:pre"> </span>l=in(),r=in(); <span style="white-space:pre"> </span>splay(find(--l)); <span style="white-space:pre"> </span>root->c[1]->is_root=1; <span style="white-space:pre"> </span>splay(find(++r)); <span style="white-space:pre"> </span>paint(root->c[0],-1,l+r); <span style="white-space:pre"> </span>root->is_root=0; <span style="white-space:pre"> </span>root=root->f; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>prt(root); }