HDU3487 play with chain

题目大意:给出1到n的有序数列,现在有两个操作:

1.CUT a b c 把第a到第b个数剪切下来,放到剩下的第c个数的后边。

2.FLIP a b  把第a到第b个数反转。

经过总共m次操作后,求现在的数列。

n,m<300000

分析:典型的splay题。包含的操作即:查找第k大,剪切,插入,反转等操作。

维护size,rev(反转标记)即可。

通过size可以找到第k大,通过rev做懒标记,可以进行反转。

具体说就是,比如要剪切CUT a,b,c,以先把第a-1个节点splay到根的位置,然后把第b+1个节点spaly到根的右儿子的位置,则a到b这一段就刚好是根的右儿子的左子树了,然后把它剪切下来。再把第c节点splay到根的位置,把第c+1个节点splay到根的右儿子的位置,再把刚才剪切的那一段接在根的右儿子的左儿子位置即可。FLIP a b的话,先把第a-1个节点splay到根的位置,把第b+1个节点splay到根的右儿子的位置,然后对根的右儿子的左子树打上懒标记即可。注意:打蓝标记应该是tree[i].rev^=1,而不是tree[i].rev=1。我就是这样wa了一次。

因为splay树的伸展特性,splay树中要增加两个额外的虚拟节点,即头节点和尾节点。初始时把头结点作为根节点,把尾节点作为根的右儿子。有效节点作为根的左儿子的右子树。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 using namespace std;
  5 #define MAXN 300505
  6 int tot,root,n,m,a,b,c;
  7 char str[10];
  8 struct node
  9 {
 10     int val,fa,sz;
 11     bool rev;
 12     int ch[2];
 13 }tree[MAXN];
 14 void newnode(int &r,int father,int val)
 15 {
 16     tot++;
 17     r=tot;
 18     tree[tot].fa=father;
 19     tree[tot].val=val;
 20 }
 21 void build(int &root,int l,int r,int father)
 22 {
 23     if(l>r)return;
 24     int mid=(l+r)/2;
 25     newnode(root,father,mid);
 26     build(tree[root].ch[0],l,mid-1,root);
 27     build(tree[root].ch[1],mid+1,r,root);
 28     tree[root].sz=tree[tree[root].ch[0]].sz+tree[tree[root].ch[1]].sz+1;
 29     }
 30 void init()
 31 {
 32     tot=root=0;
 33     memset(tree,0,sizeof tree);
 34     newnode(root,0,-1);
 35     newnode(tree[root].ch[1],root,-1);
 36     build(tree[tree[1].ch[1]].ch[0],1,n,tree[1].ch[1]);
 37     tree[tree[1].ch[1]].sz=tree[tree[tree[1].ch[1]].ch[0]].sz+1;
 38     tree[1].sz=tree[tree[1].ch[1]].sz+1;
 39 }
 40 void pd(int &r)
 41 {
 42     if(tree[r].rev==1)
 43     {swap(tree[r].ch[0],tree[r].ch[1]);
 44         tree[tree[r].ch[0]].rev^=1;
 45         tree[tree[r].ch[1]].rev^=1;
 46         tree[r].rev=0;
 47     }
 48     
 49 }
 50 void pu(int &r)
 51 {
 52     tree[r].sz=tree[tree[r].ch[0]].sz+tree[tree[r].ch[1]].sz+1;
 53     }
 54 void rotato(int &r,bool kind)
 55 {
 56     int y=tree[r].fa;
 57     int yy=tree[y].fa;
 58     if(yy)
 59     {
 60         tree[yy].ch[tree[yy].ch[1]==y]=r;
 61         }
 62         tree[r].fa=yy;
 63         tree[tree[r].ch[kind]].fa=y;
 64     tree[y].ch[!kind]=tree[r].ch[kind];
 65         tree[y].fa=r;
 66         tree[r].ch[kind]=y;
 67         pu(y);
 68         pu(r);
 69 }
 70 void splay(int &r,int goal)
 71 {
 72     while(tree[r].fa!=goal)
 73     {
 74         int y=tree[r].fa;
 75         int yy=tree[y].fa;
 76         if(yy==goal)rotato(r,tree[y].ch[0]==r);
 77         else
 78         {
 79             int kind=(tree[y].ch[0]==r);
 80             if(tree[yy].ch[kind]==y)
 81             {
 82                 rotato(r,kind);
 83                 rotato(r,!kind);
 84             }
 85             else
 86             {
 87                 rotato(y,kind);
 88                 rotato(r,kind);
 89             }
 90         }
 91     }
 92     if(goal==0)
 93         root=r;
 94 }
 95 int find(int r,int k)
 96     {
 97     pd(r);
 98     if(tree[tree[r].ch[0]].sz==k-1)
 99         return r;
100     else if(tree[tree[r].ch[0]].sz>k-1)
101         return find(tree[r].ch[0],k);
102         else return find(tree[r].ch[1],k-tree[tree[r].ch[0]].sz-1);
103     }
104     void print(int &r)
105     {
106     pd(r);
107     if(tree[r].ch[0])
108     print(tree[r].ch[0]);    
109         if(tree[r].val!=-1){printf("%d",tree[r].val);if(tot>3)printf(" ");tot--;}
110         if(tree[r].ch[1])
111         print(tree[r].ch[1]);
112     }
113 int main()
114 {
115     
116     while(scanf("%d%d",&n,&m)&&(n>=0&&m>=0))
117     {
118     init();
119     for(int i=0;i<m;i++)
120     {
121         scanf("%s",str);
122         if(str[0]=='C')
123         {
124             scanf("%d%d%d",&a,&b,&c);
125             int x1=find(root,a);
126             int y1=find(root,b+2);
127             splay(x1,0);
128             splay(y1,root);
129             int t=tree[tree[root].ch[1]].ch[0];
130             tree[tree[root].ch[1]].ch[0]=0;
131             pu(tree[root].ch[1]);
132             pu(root);
133             x1=find(root,c+1);
134             y1=find(root,c+2);
135             splay(x1,0);
136             splay(y1,root);
137             tree[tree[root].ch[1]].ch[0]=t;
138             tree[t].fa=tree[root].ch[1];
139             pu(tree[root].ch[1]);
140             pu(root);
141         }
142         else 
143         {
144             scanf("%d%d",&a,&b);
145             int x=find(root,a);
146             int y=find(root,b+2);
147             splay(x,0);
148             splay(y,root);
149             tree[tree[tree[root].ch[1]].ch[0]].rev^=1;
150         }
151     }
152     print(root);
153     printf("
");
154     }
155 }
View Code
原文地址:https://www.cnblogs.com/hefenghhhh/p/4650519.html