HDU 4453 Looploop(Splay伸展树)

【题意】一圆环,有一个指针指着某个位置,初值指着1,按照顺时针方向计数。6种操作,插入数、区间加、询问点、区间翻转、删除点、指针移动。

【分析】破环为链,裸的Splay伸展树。

 

模板被我写挫了。

  1 #include<stdio.h>
  2 #include<math.h>
  3 #include<string.h>
  4 #include<algorithm>
  5 
  6 using namespace std;
  7 
  8 #define keyTree ch[ch[root][1]][0]
  9 
 10 const int maxn = 510002;
 11 
 12 int N, M, K1, K2;
 13 int wh;
 14 
 15 struct SplayTree
 16 {
 17     int sz[maxn];
 18     int ch[maxn][2];
 19     int pre[maxn];
 20     int root , top1 ;
 21 
 22     void Rotate(int x,int f)
 23     {
 24         int y = pre[x];
 25         push_down(y);
 26         push_down(x);
 27         ch[y][!f] = ch[x][f];
 28         pre[ ch[x][f] ] = y;
 29         pre[x] = pre[y];
 30         if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] = x;
 31         ch[x][f] = y;
 32         pre[y] = x;
 33         push_up(y);
 34     }
 35     void Splay(int x,int goal)
 36     {
 37         push_down(x);
 38         //puts("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz");
 39         while(pre[x] != goal)
 40         {
 41             int y = pre[x], z = pre[y];
 42             push_down(z);
 43             push_down(y);
 44             push_down(x);
 45             if(pre[pre[x]] == goal)
 46             {
 47                 Rotate(x , ch[pre[x]][0] == x);
 48             }
 49             else
 50             {
 51                 int y = pre[x] , z = pre[y];
 52                 int f = (ch[z][0] == y);
 53                 if(ch[y][f] == x)
 54                 {
 55                     Rotate(x , !f) , Rotate(x , f);
 56                 }
 57                 else
 58                 {
 59                     Rotate(y , f) , Rotate(x , f);
 60                 }
 61             }
 62         }
 63         push_up(x);
 64         if(goal == 0) root = x;
 65     }
 66     void RotateTo(int k,int goal)  //把第k位的数转到goal下边
 67     {
 68         int x = root;
 69         push_down(x);
 70         while(sz[ ch[x][0] ] != k)
 71         {
 72             // printf("x = %d k = %d sz[x] = %d\n",x,k,sz[x]);
 73             if(k < sz[ ch[x][0] ])
 74             {
 75                 x = ch[x][0];
 76             }
 77             else
 78             {
 79                 k -= (sz[ ch[x][0] ] + 1);
 80                 x = ch[x][1];
 81             }
 82             push_down(x);
 83         }
 84         Splay(x,goal);
 85     }
 86 
 87 
 88     void debug()
 89     {
 90         printf("%d\n",root);
 91         Treaval(root);
 92     }
 93     void Treaval(int x)
 94     {
 95         push_down(x);
 96         if(x)
 97         {
 98             Treaval(ch[x][0]);
 99             printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]);
100             Treaval(ch[x][1]);
101         }
102     }
103 
104 
105     void NewNode(int &x,int c)
106     {
107         x = ++top1;
108         ch[x][0] = ch[x][1] = pre[x] = 0;
109         sz[x] = 1;
110 
111         val[x] = c;/*这是题目特定函数*/
112         lazy[x] = 0;
113         add[x] = 0;
114     }
115 
116     //把延迟标记推到孩子
117     void push_down(int x)  /*这是题目特定函数*/
118     {
119         int l = ch[x][0];
120         int r = ch[x][1];
121         if (lazy[x] != 0)
122         {
123             rev(l);
124             rev(r);
125             lazy[x] = 0;
126         }
127         if (add[x] != 0)
128         {
129             add[l] += add[x];
130             add[r] += add[x];
131             val[l] += add[x];
132             val[r] += add[x];
133             add[x] = 0;
134         }
135     }
136     //把孩子状态更新上来
137     void push_up(int x)
138     {
139         sz[x] = 1 + sz[ ch[x][0] ] + sz[ ch[x][1] ];
140         /*以下这是题目特定函数*/
141         //um[x] = add[x] + val[x] + sum[ ch[x][0] ] + sum[ ch[x][1] ];
142     }
143 
144     /*初始化*/
145     void makeTree(int &x,int l,int r,int f)
146     {
147         if(l > r) return ;
148         int m = (l + r)>>1;
149         NewNode(x , num[m]);        /*num[m]权值改成题目所需的*/
150         makeTree(ch[x][0] , l , m - 1 , x);
151         makeTree(ch[x][1] , m + 1 , r , x);
152         pre[x] = f;
153         push_up(x);
154     }
155     void init(int n)
156     {
157         ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0;
158         add[0] = sum[0] = 0;
159 
160         NewNode(root , -1);
161         NewNode(ch[root][1] , -1);
162         pre[top1] = root;
163         sz[root] = 2;
164 
165         cnt = n;
166         wh = 1;
167 
168 
169         for (int i=1; i<=n; i++)
170         {
171             scanf("%d",&num[i]);
172         }
173         makeTree(keyTree, 1, n, ch[root][1]);
174         push_up(ch[root][1]);
175         push_up(root);
176         //Treaval(root);
177     }
178 
179     void rev(int x)
180     {
181         if (x == 0)
182             return ;
183         swap(ch[x][0], ch[x][1]);
184         lazy[x] ^= 1;
185     }
186     int query()
187     {
188         int k = wh;
189         int x = root;
190         push_down(x);
191         while (sz[ch[x][0]] != k)
192         {
193             //printf("x %d k %d %d\n",x,k,sz[ch[x][0]]);
194             if (k < sz[ch[x][0]])
195             {
196                 x = ch[x][0];
197             }
198             else
199             {
200                 k -= (sz[ch[x][0]] + 1);
201                 x = ch[x][1];
202             }
203             push_down(x);
204         }
205         //printf("x = %d\n",x);
206         return val[x];
207     }
208     void add_value(int l,int r,int x)
209     {
210         RotateTo(l-1, 0);
211         RotateTo(r+1, root);
212         add[keyTree] += x;
213         val[keyTree] += x;
214         push_up(ch[root][1]);
215         push_up(root);
216     }
217     void update(int x)
218     {
219         int l, r;
220         if (wh + K2 - 1<=cnt)
221         {
222             l = wh;
223             r = wh + K2 - 1;
224             add_value(l,r,x);
225         }
226         else
227         {
228             l = wh;
229             r = cnt;
230             add_value(l,r,x);
231 
232             l = 1;
233             r = (wh + K2 -1 - cnt);
234             add_value(l,r,x);
235         }
236     }
237     void hebin(int k,int s)
238     {
239         RotateTo(k-1, 0);
240         RotateTo(k, root);
241 
242         keyTree = s;
243         pre[s] = ch[root][1];
244         push_up(ch[root][1]);
245         push_up(root);
246     }
247     void insert(int x)
248     {
249         RotateTo(wh, 0);
250         RotateTo(wh+1,root);
251         NewNode(keyTree, x);
252         pre[keyTree] = ch[root][1];
253         push_up(ch[root][1]);
254         push_up(root);
255 
256         cnt++;
257     }
258     void dele()
259     {
260         RotateTo(wh-1, 0);
261         RotateTo(wh+1, root);
262         keyTree = 0;
263         push_up(ch[root][1]);
264         push_up(root);
265 
266         if (wh == cnt)
267         {
268             wh = 1;
269         }
270         cnt--;
271     }
272     void move(int x)
273     {
274         if (x == 1)
275         {
276             wh--;
277         }
278         else
279         {
280             wh++;
281         }
282         if (wh==0)
283         {
284             wh = cnt;
285         }
286         if (wh == cnt+1)
287         {
288             wh = 1;
289         }
290     }
291     void lz(int l, int r)
292     {
293         RotateTo(l-1, 0);
294         RotateTo(r+1, root);
295         rev(keyTree);
296     }
297     void fanzhuan()
298     {
299         if (wh + K1-1 <=cnt)
300         {
301             lz(wh, wh + K1 - 1);
302         }
303         else
304         {
305             int p1, p2 , p3, p4;
306             p4 = cnt;
307             p1 = wh + K1 -1 - cnt;
308             p2 = split(1, p1);
309             wh = wh - p1;
310             p4 = p4 - p1;
311             hebin(p4+1, p2);
312             p1 = wh + K1 - 1;
313             lz(wh, p1);
314         }
315     }
316     int split(int l, int r)
317     {
318         RotateTo(l-1, 0);
319         RotateTo(r+1, root);
320         int res = keyTree;
321         keyTree = 0;
322         push_up(ch[root][1]);
323         push_up(root);
324         return res;
325     }
326     int cnt;
327     int val[maxn];
328     int sum[maxn];
329     int add[maxn];
330     int num[maxn];
331     int lazy[maxn];
332 } spt;
333 
334 int main()
335 {
336     char str[20];
337     int x;
338     int cast = 0;
339     while (scanf("%d%d%d%d", &N,&M,&K1,&K2))
340     {
341         if (N == 0 && M==0)
342             break;
343         spt.init(N);
344         printf("Case #%d:\n",++cast);
345 
346         while (M--)
347         {
348             scanf("%s",str);
349             if (str[0] == 'a')
350             {
351                 scanf("%d",&x);
352                 spt.update(x);
353             }
354             else if (str[0] == 'r')
355             {
356                 spt.fanzhuan();
357             }
358             else if (str[0] == 'i')
359             {
360                 scanf("%d",&x);
361                 spt.insert(x);
362             }
363             else if (str[0] == 'd')
364             {
365                 spt.dele();
366             }
367             else if (str[0] == 'm')
368             {
369                 scanf("%d",&x);
370                 spt.move(x);
371             }
372             else
373             {
374                 int ans = spt.query();
375                 printf("%d\n",ans);
376             }
377         }
378     }
379     return 0;
380 }
hdu4453

 

转载于:https://www.cnblogs.com/wangsouc/articles/3652762.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值