首页 > 代码库 > hdu 3487 Play with Chain(splay区间剪切,翻转)

hdu 3487 Play with Chain(splay区间剪切,翻转)

题目链接:hdu 3487 Play with Chain

题意:

cut a b c:

将a到b区间剪切下来,放在第c位置的后面。

flip a b:

翻转a到b区间

题解:

第一个操作,选通过旋转,然后使a到b区间变成根的右儿子的左儿子,然后剪掉。

再找到c+1的位置,接上。

第二个操作,区间标记就行。

技术分享
  1 #include<bits/stdc++.h>
  2 #define F(i,a,b) for(int i=a;i<=b;++i)
  3 using namespace std;
  4 const int N=1e6+7;
  5 int _t;
  6 
  7 struct Splay_tree
  8 {
  9     int root,q[N];bool rev[N];
 10     int key[N],sz[N],f[N],ch[N][2];
 11     void rev1(int x){if(x)swap(ch[x][0],ch[x][1]),rev[x]^=1;}
 12     inline void nw(int &x,int val,int fa)
 13     {
 14         x=++_t,key[x]=val,f[x]=fa,sz[x]=1;
 15         ch[x][0]=ch[x][1]=0;
 16         rev[x]=0;
 17     }
 18     inline void pd(int x){if(rev[x])rev1(ch[x][0]),rev1(ch[x][1]),rev[x]=0;}
 19     inline void up(int x){sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;}
 20     void rotate(int x){
 21         int y=f[x],w=ch[y][1]==x;
 22         ch[y][w]=ch[x][w^1];
 23         if(ch[x][w^1])f[ch[x][w^1]]=y;
 24         if(f[y]){
 25             int z=f[y];
 26             if(ch[z][0]==y)ch[z][0]=x;
 27             if(ch[z][1]==y)ch[z][1]=x;
 28         }
 29         f[x]=f[y],ch[x][w^1]=y,f[y]=x,up(y);
 30     }
 31     void splay(int x,int w){
 32         int s=1,i=x,y;q[1]=x;
 33         while(f[i])q[++s]=i=f[i];
 34         while(s)pd(q[s--]);
 35         while(f[x]!=w){
 36             y=f[x];
 37             if(f[y]!=w){if((ch[f[y]][0]==y)^(ch[y][0]==x))rotate(x);else rotate(y);}
 38             rotate(x);
 39         }
 40         if(!w)root=x;
 41         up(x);
 42     }
 43     void build(int &x,int l,int r,int fa=0)//按照数组下标建树
 44     {
 45         if(l>r)return;
 46         int mid=l+r>>1;
 47         nw(x,mid,fa);
 48         build(ch[x][0],l,mid-1,x);
 49         build(ch[x][1],mid+1,r,x);
 50         up(x);
 51     }
 52     inline int kth(int k)//获得第k小
 53     {
 54         if(k>sz[root]||k<=0)return 0;
 55         int x=root,tmp;
 56         while(1)
 57         {
 58             pd(x),tmp=sz[ch[x][0]]+1;
 59             if(k==tmp)break;
 60             if(k<tmp)x=ch[x][0];else k-=tmp,x=ch[x][1];
 61         }
 62         return x;
 63     }
 64     void reverse(int a,int b)//翻转a到b区间
 65     {
 66         splay(kth(a),0),splay(kth(b+2),root);
 67         rev1(ch[ch[root][1]][0]);
 68     }
 69     void cut(int a,int b,int c)
 70     {
 71         splay(kth(a),0),splay(kth(b+2),root);
 72         int tmp=ch[ch[root][1]][0];
 73         ch[ch[root][1]][0]=0;
 74         pd(ch[root][1]),pd(root);
 75         splay(kth(c+1),0);
 76         splay(kth(c+2),root);
 77         ch[ch[root][1]][0]=tmp;
 78         f[ch[ch[root][1]][0]]=ch[root][1];
 79         up(ch[root][1]),up(root);
 80     }
 81 }spt;
 82 //--------------------------------
 83 
 84 int n,m,cnt;
 85 
 86 void out(int x)
 87 {
 88     if(!x)return;
 89     spt.pd(x),out(spt.ch[x][0]);
 90     if(spt.key[x]>1&&spt.key[x]<n+2)printf("%d%c",spt.key[x]-1," \n"[++cnt==n]);
 91     out(spt.ch[x][1]);
 92 }
 93 
 94 int main()
 95 {
 96     while(~scanf("%d%d",&n,&m))
 97     {
 98         if(n==-1)break;
 99         _t=0,spt.build(spt.root,1,n+2);
100         char cmd[10];
101         int a,b,c;
102         F(i,1,m)
103         {
104             scanf("%s",cmd);
105             if(cmd[0]==C)
106             {
107                 scanf("%d%d%d",&a,&b,&c);
108                 spt.cut(a,b,c);
109             }else scanf("%d%d",&a,&b),spt.reverse(a,b);
110         }
111         cnt=0,out(spt.root);
112     }
113     return 0;
114 }
View Code

 

hdu 3487 Play with Chain(splay区间剪切,翻转)