HDU--3487 Play with Chain (Splay伸展树)

Play with Chain

Problem Description
YaoYao is fond of playing his chains. He has a chain containing n diamonds on it. Diamonds are numbered from 1 to n.
At first, the diamonds on the chain is a sequence: 1, 2, 3, …, n.
He will perform two types of operations:
CUT a b c: He will first cut down the chain from the ath diamond to the bth diamond. And then insert it after the cth diamond on the remaining chain.
For example, if n=8, the chain is: 1 2 3 4 5 6 7 8; We perform “CUT 3 5 4”, Then we first cut down 3 4 5, and the remaining chain would be: 1 2 6 7 8. Then we insert “3 4 5” into the chain before 5th diamond, the chain turns out to be: 1 2 6 7 3 4 5 8.

FLIP a b: We first cut down the chain from the ath diamond to the bth diamond. Then reverse the chain and put them back to the original position.
For example, if we perform “FLIP 2 6” on the chain: 1 2 6 7 3 4 5 8. The chain will turn out to be: 1 4 3 7 6 2 5 8

He wants to know what the chain looks like after perform m operations. Could you help him? 
 
Input
There will be multiple test cases in a test data. 
For each test case, the first line contains two numbers: n and m (1≤n, m≤3*100000), indicating the total number of diamonds on the chain and the number of operations respectively.
Then m lines follow, each line contains one operation. The command is like this:
CUT a b c // Means a CUT operation, 1 ≤ a ≤ b ≤ n, 0≤ c ≤ n-(b-a+1).
FLIP a b    // Means a FLIP operation, 1 ≤ a < b ≤ n.
The input ends up with two negative numbers, which should not be processed as a case.
 
Output
For each test case, you should print a line with n numbers. The ith number is the number of the ith diamond on the chain.
 
Sample Input
8 2
CUT 3 5 4
FLIP 2 6 -1 -1
 
Sample Output
1 4 3 7 6 2 5 8
 
Source
题意:FLIP操作就是区间的翻转,而CUT则是把某个区间移到某个点后面,本来打算用几次翻转来合成CUT函数,最后没有推出来。so借鉴kuangbin巨巨的作法
  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <algorithm>
  4 using namespace std;
  5 const int maxn = 3e5+10;
  6 int siz[maxn],pre[maxn],ch[maxn][2],rev[maxn],key[maxn];
  7 int tot,root,n,m;
  8 void NewNode(int &r,int father,int k)
  9 {
 10     r = ++tot;
 11     pre[r] = father;
 12     ch[r][0] = ch[r][1] = 0;
 13     key[r] = k;
 14     siz[r] = 1;
 15     rev[r] = 0;
 16 }
 17 void update_rev(int r)
 18 {
 19     if (!r)
 20         return ;
 21     swap(ch[r][0],ch[r][1]);
 22     rev[r] ^= 1;
 23 }
 24 void push_up(int r)
 25 {
 26     siz[r] = siz[ch[r][0]] + siz[ch[r][1]] + 1;
 27 }
 28 void push_down(int r)
 29 {
 30     if (rev[r])
 31     {
 32         update_rev(ch[r][0]);
 33         update_rev(ch[r][1]);
 34         rev[r] = 0;
 35     }
 36 }
 37 void build(int &x,int l,int r,int father)
 38 {
 39     if (l > r)
 40         return;
 41     int mid = (l + r) >> 1;
 42     NewNode(x,father,mid);
 43     build(ch[x][0],l,mid-1,x);
 44     build(ch[x][1],mid+1,r,x);
 45     push_up(x);
 46 }
 47 void init()
 48 {
 49     root = tot = 0;
 50     NewNode(root,0,-1);
 51     NewNode(ch[root][1],root,-1);
 52     build(ch[ch[root][1]][0],1,n,ch[root][1]);
 53     push_up(ch[root][1]);
 54     push_up(root);
 55 }
 56 
 57 void Rotate(int x,int kind)
 58 {
 59     int y = pre[x];
 60     push_down(y);
 61     push_down(x);
 62     ch[y][!kind] = ch[x][kind];
 63     pre[ch[x][kind]] = y;
 64     if (pre[y])
 65         ch[pre[y]][ch[pre[y]][1] == y] = x;
 66     pre[x] = pre[y];
 67     ch[x][kind] = y;
 68     pre[y] = x;
 69     push_up(y);
 70 }
 71 
 72 void Splay(int r,int goal)
 73 {
 74     push_down(r);
 75     while (pre[r] != goal)
 76     {
 77         if (pre[pre[r]] == goal)
 78         {
 79             push_down(pre[r]);
 80             push_down(r);
 81             Rotate(r,ch[pre[r]][0] == r);
 82         }
 83         else
 84         {
 85             int y = pre[r];
 86             int kind = (ch[pre[y]][1] == y);
 87             push_down(pre[y]);
 88             push_down(y);
 89             push_down(r);
 90             if (ch[y][kind] == r)
 91             {
 92                 Rotate(y,!kind);
 93                 Rotate(r,!kind);
 94             }
 95             else
 96             {
 97                 Rotate(r,kind);
 98                 Rotate(r,!kind);
 99             }
100         }
101     }
102     push_up(r);
103     if (goal == 0)
104         root = r;
105 }
106 int Get_kth(int r,int k)
107 {
108     push_down(r);
109     int t = siz[ch[r][0]] + 1;
110     if (k == t)
111         return r;
112     if (k >= t)
113         return Get_kth(ch[r][1],k-t);
114     else
115         return Get_kth(ch[r][0],k);
116 }
117 void Reverse(int u,int v)
118 {
119     if (u > v)
120         return;
121     Splay(Get_kth(root,u),0);
122     Splay(Get_kth(root,v+2),root);
123     update_rev(ch[ch[root][1]][0]);
124     push_up(ch[root][1]);
125     push_up(root);
126 }
127 void cut(int x,int y,int z)          // cut函数本来想着用几次翻转来实现,推了半天没有推出来。so借鉴kuangbin巨巨的做法
128 {
129     Splay(Get_kth(root,x),0);
130     Splay(Get_kth(root,y+2),root);
131     int tmp = ch[ch[root][1]][0];
132     ch[ch[root][1]][0] = 0;
133     push_up(ch[root][1]);
134     push_up(root);
135     Splay(Get_kth(root,z+1),0);
136     Splay(Get_kth(root,z+2),root);
137     ch[ch[root][1]][0] = tmp;
138     pre[ch[ch[root][1]][0]] = ch[root][1];
139     push_up(ch[root][1]);
140     push_up(root);
141 }
142 bool flag;
143 void dfs(int r)
144 {
145     if (!r)
146         return;
147     push_down(r);
148     dfs(ch[r][0]);
149     if (r != -1 && key[r] != -1)
150     {
151         printf(flag ? " %d":"%d",key[r]);
152         flag = 1;
153     }
154     dfs(ch[r][1]);
155 }
156 int main(void)
157 {
158     #ifndef ONLINE_JUDGE
159         freopen("in.txt","r",stdin);
160     #endif
161     while (~scanf ("%d%d",&n,&m))
162     {
163         if (n < 0 && m < 0)
164             break;
165         init();
166         for (int i = 0; i < m; i++)
167         {
168             char op[6];
169             int x,y,z;
170             scanf ("%s",op);
171             if (op[0] == 'C')
172             {
173                 scanf ("%d%d%d",&x,&y,&z);
174                 cut(x,y,z);
175             }
176             else
177             {
178                 scanf ("%d%d",&x,&y);
179                 Reverse(x,y);
180             }
181         }
182         flag = 0;
183         dfs(root);
184         printf("\n");
185     }
186     return 0;
187 }

 

posted @ 2014-11-07 20:39  PlasticSpirit  阅读(165)  评论(0编辑  收藏  举报