标签:
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; const int INF=1e9+7; const int maxn=300005; int N,M,ans,A[maxn],cnt; //A数组保存数,cnt是节点标号,我是用数组模拟的 struct treap { treap* son[2]; //左右儿子 int v,s,rev; treap(){ v=s=rev=0; son[0]=son[1]=NULL; } treap(int nv); int rk(){ return son[0]->s+1; } //排名,第几个数 int cmp(int k) //比较,如果相等返回-1,小于返回0,大于1 { if(k==rk()) return -1; return k<rk()?0:1; } void pushup(){ s=son[0]->s+son[1]->s+1; } //更新大小 void pushdown(); //处理懒惰标记 }null,tr[maxn]; treap::treap(int nv) { v=nv; s=1; rev=0; son[0]=son[1]=&null; } void treap::pushdown() { if(this==&null) return; if(rev) { swap(son[0],son[1]); son[0]->rev^=1; son[1]->rev^=1; rev=0; } } treap* NewNode(int x) { tr[cnt]=treap(x); return tr+cnt++; } struct splaytree { int Size; treap* root; splaytree(){ Size=0; root=&null; } void Rotate(treap* &t,int d) //翻转操作 { t->pushdown(); treap* p=t->son[d^1]; p->pushdown(); t->son[d^1]=p->son[d]; p->son[d]=t; t->pushup(); t=p; t->pushup(); } void Splay(treap* &t,int k) //将第k大的节点伸展到根 { t->pushdown(); int d=t->cmp(k); if(d!=-1) { if(d) Splay(t->son[d],k- t->rk()); else Splay(t->son[d],k); Rotate(t,d^1); } t->pushup(); } void Build(treap* &t,int le,int ri) //将N个数建成一棵树 { if(le>ri) return; int mid=(le+ri)/2; t=NewNode(mid); Build(t->son[0],le,mid-1); Build(t->son[1],mid+1,ri); t->pushup(); } void Cut(treap* &t,int a,int b,int c) { int len=b-a+1; if(len==N) return; //是整个区间就不用管了 Splay(t,a); t->pushdown(); //分裂出左边的 treap *L=t->son[0]; L->pushdown(); t->son[0]=&null; t->pushup(); Splay(t,len); t->pushdown(); //分裂出右边的 treap *R=t->son[1]; R->pushdown(); t->son[1]=&null; t->pushup(); treap *nt; if(R!=&null) //左右合并 { nt=R; Splay(nt,1); nt->son[0]=L; nt->pushup(); } else { nt=L; Splay(nt,a-1); nt->son[1]=R; nt->pushup(); } if(c+len==N) //在整个之后特殊处理一下就好 { Splay(nt,c); Splay(t,1); t->son[0]=nt; t->pushup(); return; } Splay(nt,c+1); treap *l=nt->son[0]; l->pushdown(); nt->son[0]=&null; nt->pushup(); t->son[1]=nt; t->pushup(); Splay(t,1); t->son[0]=l; t->pushup(); } void Reverse(treap* &t,int a,int b) //翻转 { Splay(t,a); //左边 treap *L=t->son[0]; L->pushdown(); t->son[0]=&null; t->pushup(); Splay(t,b-a+1); //右边 treap *R=t->son[1]; R->pushdown(); t->son[1]=&null; t->pushup(); t->rev^=1; //置翻转标记 t->pushdown(); t->son[0]=L; t->pushup(); Splay(t,b); t->son[1]=R; t->pushup(); } void PushAll(treap* &t) //中序遍历 { if(t==&null) return; t->pushdown(); PushAll(t->son[0]); A[++ans]=t->v; PushAll(t->son[1]); t->pushup(); } }; int main() { while(scanf("%d%d",&N,&M)!=EOF) { if(N<0&&M<0) break; splaytree spt; cnt=0; spt.Build(spt.root,1,N); //建树 int a,b,c; char op[10]; while(M--) { scanf("%s",op); if(op[0]==‘C‘) //CUT操作 { scanf("%d%d%d",&a,&b,&c); spt.Cut(spt.root,a,b,c); } else //FLIP操作 { scanf("%d%d",&a,&b); spt.Reverse(spt.root,a,b); } } ans=0; spt.PushAll(spt.root); //整个下压 for(int i=1;i<=ans;i++) printf("%d%c",A[i],i==ans?‘\n‘:‘ ‘); } return 0; }
Hdu3487-Play with Chain(伸展树分裂合并)
标签:
原文地址:http://www.cnblogs.com/wust-ouyangli/p/5734351.html