题目大意

给一个数列,初始时为 1, 2, 3, ..., n,现在有两种共 m 个操作

  操作1. CUT a b c 表示把数列中第 a 个到第 b 个从原数列中删除得到一个新数列,并将它添加到新数列中第 c 个数的后面

  操作2. FLIP a b 表示把数列中第 a 个数到第 b 个数翻转

经过 m 个操作之后,输出这个数列

1≤n, m≤3*100000

做法分析

这题也不好用线段树做,用 Splay 很快就搞出来了

对于"操作1. CUT a b c" ,只需要将 a-1 旋转到根,b+1旋转成 a-1 的子树,那么 [a, b] 之间的树变成了 b+1 的左子树,将整个子树从原树中删去,并把 b+1 旋转到根。之后把 c 旋转到根,c+1 旋转成 c 的子树,再把刚才删掉的子树添加到 c+1 的左子树上(没添加之前,c+1 的左子树必然为空)

对于“操作2. FLIP a b”,只需要给树中每个节点一个 rev 标记表示是否需要翻转以该节点为根的子树中序遍历所得的数列,和线段树差不多的使用懒操作就行了

还是那些细节问题,在什么时候 pushDown,什么时候 pushUp,写代码的时候一定要想清楚

参考代码

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <queue>
  5
  6 using namespace std;
  7
  8 const int N=300005, INF=0x7fffffff;
  9
 10 struct Splay_Tree {
 11     struct Node {
 12         int val, Size, son[2];
 13         bool rev;
 14         inline void init(int _val) {
 15             val=_val, Size=1;
 16             son[0]=son[1]=rev=0;
 17         }
 18     } T[N];
 19     int fa[N], root;
 20     queue <int> ans;
 21
 22     inline void pushUp(int x) {
 23         T[x].Size=1;
 24         if(T[x].son[0]) T[x].Size+=T[T[x].son[0]].Size;
 25         if(T[x].son[1]) T[x].Size+=T[T[x].son[1]].Size;
 26     }
 27
 28     inline void pushDown(int x) {
 29         if(!T[x].rev) return;
 30         if(T[x].son[0]) T[T[x].son[0]].rev^=1;
 31         if(T[x].son[1]) T[T[x].son[1]].rev^=1;
 32         swap(T[x].son[0], T[x].son[1]);
 33         T[x].rev=0;
 34     }
 35
 36     void Rotate(int x, int kind) {
 37         int y=fa[x], z=fa[y];
 38         pushDown(y), pushDown(x);
 39         T[y].son[!kind]=T[x].son[kind], fa[T[x].son[kind]]=y;
 40         T[x].son[kind]=y, fa[y]=x;
 41         T[z].son[T[z].son[1]==y]=x, fa[x]=z;
 42         pushUp(y);
 43     }
 44
 45     void Splay(int x, int goal) {
 46         if(x==goal) return;
 47         while(fa[x]!=goal) {
 48             int y=fa[x], z=fa[y];
 49             int rx=T[y].son[0]==x, ry=T[z].son[0]==y;
 50             if(z==goal) Rotate(x, rx);
 51             else {
 52                 if(rx==ry) Rotate(y, ry);
 53                 else Rotate(x, rx);
 54                 Rotate(x, ry);
 55             }
 56         }
 57         pushUp(x);
 58         if(goal==0) root=x;
 59     }
 60
 61     int Select(int pos, int goal) {
 62         int u=root;
 63         pushDown(u);
 64         while(T[T[u].son[0]].Size!=pos) {
 65             if(T[T[u].son[0]].Size>pos) u=T[u].son[0];
 66             else {
 67                 pos-=T[T[u].son[0]].Size+1;
 68                 u=T[u].son[1];
 69             }
 70             pushDown(u);
 71         }
 72         Splay(u, goal);
 73         return u;
 74     }
 75
 76     void Cut(int L, int R, int pos) {
 77         int u=Select(L-1, 0), v=Select(R+1, u);
 78         int x=T[v].son[0];
 79         fa[x]=0, T[v].son[0]=0;
 80         Splay(v, 0);
 81         u=Select(pos, 0), v=Select(pos+1, u);
 82         T[v].son[0]=x, fa[x]=v;
 83         Splay(x, 0);
 84     }
 85
 86     void Reverse(int L, int R) {
 87         int u=Select(L-1, 0), v=Select(R+1, u);
 88         T[T[v].son[0]].rev^=1;
 89     }
 90
 91     void DFS(int u) {
 92         pushDown(u);
 93         if(T[u].son[0]) DFS(T[u].son[0]);
 94         ans.push(T[u].val);
 95         if(T[u].son[1]) DFS(T[u].son[1]);
 96     }
 97
 98     void Display(int n) {
 99         while(!ans.empty()) ans.pop();
100         DFS(root);
101         for(int cnt=0, x; cnt<n; cnt++, ans.pop()) {
102             for(x=ans.front(); x==-INF; ans.pop(), x=ans.front());
103             printf("%d", x);
104             if(cnt+1==n) printf("\n");
105             else printf(" ");
106         }
107     }
108
109     int build(int L, int R) {
110         if(L>R) return 0;
111         if(L==R) return L;
112         int mid=(L+R)>>1, sL, sR;
113         T[mid].son[0]=sL=build(L, mid-1);
114         T[mid].son[1]=sR=build(mid+1, R);
115         fa[sL]=fa[sR]=mid;
116         pushUp(mid);
117         return mid;
118     }
119
120     void init(int n) {
121         T[0].init(-INF), T[1].init(-INF), T[n+2].init(-INF);
122         for(int i=2; i<=n+1; i++) T[i].init(i-1);
123         root=build(1, n+2);
124         T[0].Size=0, T[0].son[1]=root, fa[root]=0, fa[0]=0;
125     }
126 } hehe;
127 int n, m;
128 char cmd[10];
129
130 int main() {
131 //    freopen("in", "r", stdin);
132     while(scanf("%d%d",&n, &m), n!=-1 || m!=-1) {
133         hehe.init(n);
134         for(int i=0, a, b, c; i<m; i++) {
135             scanf("%s", cmd);
136             if(cmd[0]=='C') {
137                 scanf("%d%d%d", &a, &b, &c);
138                 hehe.Cut(a, b, c);
139             }
140             else {
141                 scanf("%d%d", &a, &b);
142                 hehe.Reverse(a, b);
143             }
144         }
145         hehe.Display(n);
146     }
147     return 0;
148 }

HDU 3487

题目链接 & AC 通道

HDU 3487 Play with Chain

转载于:https://www.cnblogs.com/zhj5chengfeng/p/3271347.html

HDU 3487 Play with Chain(Splay)相关推荐

  1. fhq_treap || BZOJ 3223: Tyvj 1729 文艺平衡树 || Luogu P3391 【模板】文艺平衡树(Splay)...

    题面: [模板]文艺平衡树(Splay) 题解:无 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<iostr ...

  2. HDU各种比赛题题解(一)

    HDU各种比赛题题解(一) Gardon-DYGG Contest 1 HDU1178 Heritage from father[水题] - 海岛Blog - CSDN博客 HDU1181 变形课[D ...

  3. 伸展树(Splay)

    伸展树(Splay) Splay 是一种二叉查找树,它通过不断将某个节点旋转到根节点,使得整棵树仍然满足二叉查找树的性质,并且保持平衡而不至于退化为链.它由 Daniel Sleator 和 Robe ...

  4. 【HDU 2612 Find a Way(BFS)】(兼BFS入门笔记)

    [HDU 2612 Find a Way(BFS)](兼BFS入门笔记) 原题入口: http://acm.hdu.edu.cn/showproblem.php?pid=2612 第一篇在CSDN的博 ...

  5. BZOJ 1503 郁闷的出纳员(splay)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1503 题意:给出一个数列(初始为空),给出一个最小值Min,当数列中的数字小于Min时自动 ...

  6. 【HDU 3400】Line belt(三分法)

    题目链接 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3400 题意 有两条传送带AB和CD,移动速度分别为p,q. 除了传送带的其他区域移动速度为r ...

  7. HDU 1222 Wolf and Rabbit(gcd)

    HDU 1222   Wolf and Rabbit   (最大公约数)解题报告 题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid= ...

  8. HDU 2639 Bone Collector II (dp)

    题目链接 Problem Description The title of this problem is familiar,isn't it?yeah,if you had took part in ...

  9. hdu 3183 A Magic Lamp (rmq)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3183 #include <stdio.h> #include <stdlib.h&g ...

最新文章

  1. 将shell脚本转为python_shell脚本将python脚本加入Linux系统服务
  2. SpringBoot定义统一的controller返回格式
  3. 查看Oracle耗时Sql
  4. php和mysql的概述_PHP的MySQL扩展:MySQL数据库概述_MySQL
  5. linux cp 目录不存在自动创建,Linux运维知识之Linux:复制并创建目标目录,如果它不存在...
  6. 6.dubbo常用的xml配置有哪些_【面试篇】必须掌握的Spring 常用注解
  7. 编写并调试一个单道处理系统的作业调度模拟程序_操作系统系列(2):操作系统发展历史...
  8. php脚本定时更新商品列表
  9. 通过apizza生成python接口测试代码
  10. python抽签代码,python:选房抽签小工具
  11. android美团点餐界面,Android 仿美团点餐页面布局介绍
  12. 研究发现多种精神疾病和肠道微生物群的紊乱有关
  13. Aircrack-ng破解WEP
  14. sequence-数据库-sjk
  15. 「 iOS知识小集 」2018 · 第 29 期
  16. 从 Uber 数据泄露事件我们可以学到什么?
  17. 用Cadence Virtuoso绘制反相器教程
  18. The type javax.servlet.http.HttpServletRequest cannot be resolved. It is indirectly referenced fro
  19. 【附源码】Python计算机毕业设计社团管理系统
  20. js 获取当前环境全局对象

热门文章

  1. asp.net源码收集
  2. python选择排序 时间复杂度
  3. flutter 弹框 dialog,flutter提示框
  4. 洛谷P1434滑雪(逆向图的遍历搜索递归+记忆化,最长路问题)
  5. MYSQL基础(事务,触发器,函数,过程指令操作)
  6. Android 注解的使用与注意事项
  7. file标签样式修改
  8. matlab画图入门篇--各种基本图形绘制的函数与实例【转载】
  9. Vue首屏加载白屏问题及解决方案
  10. mysql 1.42_MySQL索引(一)