【HDU3487】【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
【分析】
果断被指针引用坑.......
调了一个半小时,本来想复习一下昨天的内容,结果被虐了。。
感觉pushdown和update出现的地方有些奇怪.
还有就是rotate里面的写法引用和不引用是不一样的。
昨天我两个都试了一下,今天就搞混了。。。。
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <vector>
  6 #include <utility>
  7 #include <iomanip>
  8 #include <string>
  9 #include <cmath>
 10 #include <queue>
 11 #include <assert.h>
 12 #include <map>
 13 #include <ctime>
 14 #include <cstdlib>
 15 #define LOCAL
 16 const int MAXN = 500000 + 10;
 17 const int INF = 100000000;
 18 const int SIZE = 450;
 19 const int maxnode =  0x7fffffff + 10;
 20 using namespace std;
 21 int M;
 22 struct SPLAY{
 23        struct Node{
 24               int val, size;
 25               bool turn;
 26               Node *ch[2], *parent;
 27               
 28               /*Node(){//暂时不要构造函数,节约时间 
 29                      val = 0;
 30                      size = 0;
 31                      turn = 0;
 32                      parent = ch[0] = ch[1] = NULL;
 33               }*/
 34               int cmp(){
 35                   if (parent->ch[0] == this) return 0;
 36                   else return 1;
 37               }
 38               //更新 
 39        }*root, *nil, _nil, mem[MAXN];
 40        int tot;
 41 
 42        void pushdown(Node *&t){
 43             if (t == nil) return;
 44             if (t->turn){
 45                Node *p;
 46                p = t->ch[0];
 47                t->ch[0] = t->ch[1];
 48                t->ch[1] = p;
 49                       
 50                if (t->ch[0] != nil) t->ch[0]->turn ^= 1;
 51                if (t->ch[1] != nil) t->ch[1]->turn ^= 1;
 52                t->turn = 0;
 53             }
 54        }
 55        void update(Node *&t){
 56             t->size = 1;
 57             t->size += t->ch[0]->size + t->ch[1]->size;
 58        }
 59        Node* NEW(int val){
 60              Node *p = &mem[tot++];
 61              p->val = val;
 62              p->size = 1;
 63              p->turn = 0;
 64              p->parent = p->ch[0] = p->ch[1] = nil; 
 65              return p;
 66        }
 67        void init(){
 68             //哨兵初始化 
 69             nil = &_nil;
 70             _nil.val = _nil.size = _nil.turn = 0;
 71             _nil.parent = _nil.ch[0] = _nil.ch[1] = nil;
 72             
 73             tot = 0;
 74             root = NEW(INF);
 75             root->ch[1] = NEW(INF);
 76             root->ch[1]->parent  = root;
 77        }
 78        //1为右旋 
 79        /*void Rotate(Node *&t, int d){
 80             Node *p = t->parent;
 81             pushdown(p);
 82             pushdown(t);
 83             pushdown(t->ch[d]);
 84             //t = p->ch[d ^ 1];这句话是废话,真正的一句一处 
 85             p->ch[d ^ 1] = t->ch[d];
 86             if (t->ch[d] != nil) t->ch[d]->parent = p;
 87             t->parent = p->parent;
 88             if (p->parent != nil) p->ch[p->cmp()] = t;
 89             t->ch[d] = p;
 90             p->parent = t;
 91             update(p);//注意这里为什么只要updatep是因为旋转是在伸展中使用的,因此t的更新在splay中 
 92             if (root == p) root = t;//换根 
 93        }*/
 94        void Rotate(Node *t, int d){
 95             Node *p = t->parent;//t的右旋对于p来说也是右旋
 96             t = p->ch[d ^ 1];
 97             p->ch[d ^ 1] = t->ch[d];
 98             t->ch[d]->parent = p;
 99             t->ch[d] = p;
100             t->parent = p->parent;
101             //注意,这里要更新的原因在于t并不是引用 
102             if (t->parent != nil){
103                if (t->parent->ch[0] == p) t->parent->ch[0] = t;
104                else if (t->parent->ch[1] == p)  t->parent->ch[1] = t;
105             }
106             p->parent = t;
107             if (t->parent == nil) root = t;
108             //不用换回去了... 
109             update(p);
110             update(t);
111             //t->update();
112        }
113        void splay(Node *x, Node *y){
114             pushdown(x);
115             while (x->parent != y){
116                   if (x->parent->parent == y){
117                      Rotate(x, x->cmp() ^ 1);
118                      break;
119                   }else{
120                      Rotate(x->parent, x->parent->cmp() ^ 1);
121                      Rotate(x, x->cmp() ^ 1);
122                   }
123                   update(x);
124             }
125             update(x);//最后退出的update不要忘了 
126             if (nil == y) root = x;
127        }
128        //找到第k小的数并将其伸展到y 
129        void find(Node *y, int k){
130             Node *x = root;
131             while (1){
132                   //if (x == nil) break;//注意我已经在init中插入了两个数 
133                   pushdown(x);
134                   int tmp = (x->ch[0]->size);
135                   if ((tmp + 1) == k) break;
136                   if (k <= tmp) x = x->ch[0];
137                   else k -= tmp + 1, x = x->ch[1]; 
138             }
139             pushdown(x);
140             splay(x, y);
141        }
142        //在pos位置后面插入一个数val 
143        void Insert(int pos, int val){
144             find(nil, pos + 1);
145             find(root, pos + 2);//时刻注意已经插入了两个INF 
146             pushdown(root);
147             pushdown(root->ch[1]);
148             Node *p = NEW(val), *t = root->ch[1];
149             //一定要拆开!!不能放在ch[1]->[0] 
150             p->ch[1] = t;
151             t->parent = p;
152             root->ch[1] = p;
153             p->parent = root;
154             splay(p, nil);
155        }
156        //剪掉a,b位置的数并接到c位置后面 
157        void Cut(int a, int b, int c){
158             find(nil, a);
159             find(root, b + 2);
160             pushdown(root);
161             pushdown(root->ch[1]);
162             
163             Node *p = root->ch[1]->ch[0];
164             root->ch[1]->ch[0] = nil;//剪掉
165             update(root->ch[1]);///不要忘了更新 
166             update(root);
167             
168             find(nil, c + 1);
169             find(root, c + 2);
170             pushdown(root);
171             pushdown(root->ch[1]);
172             
173             root->ch[1]->ch[0] = p;
174             p->parent = root->ch[1];
175             update(root->ch[1]);
176             update(root);
177             splay(p, nil); 
178        }
179        void Reverse(int l, int r){
180             find(nil, l);
181             find(root, r + 2);
182             //print(root);
183             root->ch[1]->ch[0]->turn ^= 1;
184             Node *p = root->ch[1]->ch[0];
185             splay(p, nil);
186        }
187        void print(Node *t){
188             if (t == nil) return;
189             pushdown(t);
190             print(t->ch[0]);
191             if (t->val != INF){
192                if (M != 1) {printf("%d ", t->val);M--;}
193                else printf("%d", t->val);
194             }
195             print(t->ch[1]);
196        }
197 }A;
198 int n, m;
199 
200 void init(){
201      A.init();
202      //scanf("%d%d", &n, &m);
203      for (int i = 0; i < n; i++){
204          A.Insert(i, i + 1);
205      }
206      //A.print(A.root);
207 }
208 void work(){
209      for (int i = 1; i <= m; i++){
210          char str[10];
211          scanf("%s", str);
212          if (str[0] == 'C'){
213             int a, b, c;
214             scanf("%d%d%d", &a, &b, &c);
215             A.Cut(a, b, c);
216          }else{
217             int l, r;
218             scanf("%d%d", &l, &r);
219             A.Reverse(l, r);
220          }
221          //A.print(A.root);
222      }
223      M = n;
224      A.print(A.root);
225 }
226 
227 int main(){
228     
229     while (scanf("%d%d", &n, &m)){
230           if (n == -1 && m == -1) break;
231           init();
232           //A.find(A.nil, 3);
233           //printf("%d", A.root->size);
234           work();
235           printf("\n");
236     }
237     return 0;
238 }
View Code

 

转载于:https://www.cnblogs.com/hoskey/p/4331616.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值