题目大意

给一个数列,初始时为 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,写代码的时候一定要想清楚

参考代码

 #include <iostream>
 #include <cstring>
 #include <cstdio>
 #include <queue>

 using namespace std;

 , INF=0x7fffffff;

 struct Splay_Tree {
     struct Node {
         ];
         bool rev;
         inline void init(int _val) {
             val=_val, Size=;
             son[]=son[]=rev=;
         }
     } T[N];
     int fa[N], root;
     queue <int> ans;

     inline void pushUp(int x) {
         T[x].Size=;
         ]) T[x].Size+=T[T[x].son[]].Size;
         ]) T[x].Size+=T[T[x].son[]].Size;
     }

     inline void pushDown(int x) {
         if(!T[x].rev) return;
         ]) T[T[x].son[]].rev^=;
         ]) T[T[x].son[]].rev^=;
         swap(T[x].son[], T[x].son[]);
         T[x].rev=;
     }

     void Rotate(int x, int kind) {
         int y=fa[x], z=fa[y];
         pushDown(y), pushDown(x);
         T[y].son[!kind]=T[x].son[kind], fa[T[x].son[kind]]=y;
         T[x].son[kind]=y, fa[y]=x;
         T[z].son[T[z].son[]==y]=x, fa[x]=z;
         pushUp(y);
     }

     void Splay(int x, int goal) {
         if(x==goal) return;
         while(fa[x]!=goal) {
             int y=fa[x], z=fa[y];
             ]==x, ry=T[z].son[]==y;
             if(z==goal) Rotate(x, rx);
             else {
                 if(rx==ry) Rotate(y, ry);
                 else Rotate(x, rx);
                 Rotate(x, ry);
             }
         }
         pushUp(x);
         ) root=x;
     }

     int Select(int pos, int goal) {
         int u=root;
         pushDown(u);
         ]].Size!=pos) {
             ]].Size>pos) u=T[u].son[];
             else {
                 pos-=T[T[u].son[]].Size+;
                 u=T[u].son[];
             }
             pushDown(u);
         }
         Splay(u, goal);
         return u;
     }

     void Cut(int L, int R, int pos) {
         , ), v=Select(R+, u);
         ];
         fa[x]=, T[v].son[]=;
         Splay(v, );
         u=Select(pos, ), v=Select(pos+, u);
         T[v].son[]=x, fa[x]=v;
         Splay(x, );
     }

     void Reverse(int L, int R) {
         , ), v=Select(R+, u);
         T[T[v].son[]].rev^=;
     }

     void DFS(int u) {
         pushDown(u);
         ]) DFS(T[u].son[]);
         ans.push(T[u].val);
         ]) DFS(T[u].son[]);
     }

     void Display(int n) {
         while(!ans.empty()) ans.pop();
         DFS(root);
         , x; cnt<n; cnt++, ans.pop()) {
             for(x=ans.front(); x==-INF; ans.pop(), x=ans.front());
             printf("%d", x);
             ==n) printf("\n");
             else printf(" ");
         }
     }

     int build(int L, int R) {
         ;
         if(L==R) return L;
         , sL, sR;
         T[mid].son[]=sL=build(L, mid-);
         T[mid].son[]=sR=build(mid+, R);
         fa[sL]=fa[sR]=mid;
         pushUp(mid);
         return mid;
     }

     void init(int n) {
         T[].init(-INF), T[].init(-INF), T[n+].init(-INF);
         ; i<=n+; i++) T[i].init(i-);
         root=build(, n+);
         T[].Size=, T[].son[]=root, fa[root]=, fa[]=;
     }
 } hehe;
 int n, m;
 ];

 int main() {
 //    freopen("in", "r", stdin);
      || m!=-) {
         hehe.init(n);
         , a, b, c; i<m; i++) {
             scanf("%s", cmd);
             ]=='C') {
                 scanf("%d%d%d", &a, &b, &c);
                 hehe.Cut(a, b, c);
             }
             else {
                 scanf("%d%d", &a, &b);
                 hehe.Reverse(a, b);
             }
         }
         hehe.Display(n);
     }
     ;
 }

HDU 3487

题目链接 & AC 通道

HDU 3487 Play with Chain

HDU 3487 Play with Chain(Splay)的更多相关文章

  1. HDU 3487:Play with Chain(Splay)

    http://acm.hdu.edu.cn/showproblem.php?pid=3487 题意:有两种操作:1.Flip l r ,把 l 到 r 这段区间 reverse.2.Cut a b c ...

  2. HDU 3478 Play with Chain (Splay树)

    这种高级数据结构太难搞了.........现在还是先照着别人的代码敲,做模板..........慢慢花时间来弄懂 #include <iostream> #include <algo ...

  3. HDU 1890:Robotic Sort(Splay)

    http://acm.hdu.edu.cn/showproblem.php?pid=1890 题意:有一个无序序列,经过不断地翻转,使得最后的序列是一个升序的序列,而且如果相同数字要使在原本序列靠前的 ...

  4. HDU 3487 Play with Chain 【Splay】

    1-n的序列,有两种操作: 1,将一段区间翻转 2,将一段区间切下来放到剩余序列的第C个数后 采用延迟更新的方法维护区间的翻转,并维护一个size域. 添加一个最大点和一个最小点,防止出界 翻转时,将 ...

  5. 【BZOJ3506】排序机械臂(Splay)

    [BZOJ3506]排序机械臂(Splay) 题面 神TMBZOJ没有题面,感谢SYC的题面 洛谷的题面也不错 题解 对于每次旋转的物体 显然可以预处理出来 现在只要模拟旋转操作就行了 至于在哪里放标 ...

  6. 【BZOJ1500】【NOI2005】维修数列(Splay)

    [BZOJ1500][NOI2005]维修数列(Splay) 题面 不想再看见这种毒瘤题,自己去BZOJ看 题解 Splay良心模板题 真的很简单 我一言不发 #include<iostream ...

  7. HDU 4441 Queue Sequence(splay)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4441 题意:一个数列,三种操作:(1)插入:找到没在当前数列中的最小的正整数i,将其插在位置p之后,并 ...

  8. hdu 3487 Play with Chain

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3487 YaoYao is fond of playing his chains. He has a c ...

  9. BZOJ 1251 序列终结者(Splay)

    题目大意 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术 ...

随机推荐

  1. 关于淘宝店铺装修弹出层popup的记录

    小龙最近做了一下下淘宝的店铺装修,里面封装的widget深不见底,刚刚整明白popup,也就是弹出层的使用方法,大神勿喷: <div class="area001">触 ...

  2. 【淘淘】Spring整合Quartz框架

    我在外面工作实习的时候,我们做的项目是一个日报子系统,也就是定时定点为公司生成一些报表数据还有一些数据反馈.这时候我们会经常用到定时任务,比如每天凌晨生成前天报表,每一小时生成汇总数据等等.当时,我做 ...

  3. CLR:基元类型、引用类型和值类型

    最新更新请访问: http://denghejun.github.io   前言 今天重新看了下关于CLR基元类型的东西,觉得还是有必要将其记录下来,毕竟这是理解CLR成功 之路上的重要一步,希望你也 ...

  4. Can not issue data manipulation statements with executeQuery() 异常处理

    1.这个异常的报错翻译过来就是 不能发出数据操纵语句与executeQuery() 2.这里要检查一下你要执行的实际SQL语句要做什么操作 查询呢?还是修改? 3.如果是修改的话,需要添加@Modif ...

  5. sof文件和NIOS II的软件(elf)合并为jic文件以使用Quartus Programmer烧写

    将Altera FPGA的sof文件和NIOS II的elf固件合并为一个jic文件以使用Quartus Programmer烧写   我们在学习和调试NIOS II工程的时候,一般都是先使用Quar ...

  6. JS模式:策略模式,感觉就是一个闭包存储信息,然后是加一些验证方法--还看了老半天

    <!DOCTYPE html> <html> <head> <title></title> </head> <body&g ...

  7. ubuntu 卸载/安装 redis

    ubuntu 卸载redis 1. 卸载软件 apt-get remove redis 2. 清除配置 apt-get remove --purge redis 3. 删除残留文件 find / -n ...

  8. 利用C#实现对excel的写操作

    一.COM interop 首先我们要了解下何为COM Interop,它是一种服务,可以使.NET Framework对象能够与COM对象通信.Visual Studio .NET 通过引入面向公共 ...

  9. 【python,排序】几种常用的排序算法,使用python实现

    1. 选择排序 -- -- def selectSort(l): for i in range(len(l)): j = i + 1 t_min = l[i] loc_min = i for j in ...

  10. 使用vagrant作为开发环境后,js报错

    当你尝试修改一个js,并且用同样的方法更新之后,会遇到类似的问题,是的,就算重启VM上任何服务,甚至重启VM,依旧没有用,当然,比起其他资源文件,浏览器的反应会强烈一些,因为浏览器会提示未知错误,而你 ...