题目大意

给一个数列,初始时为 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; const int N=, INF=0x7fffffff; struct Splay_Tree {
struct Node {
int val, Size, son[];
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=;
if(T[x].son[]) T[x].Size+=T[T[x].son[]].Size;
if(T[x].son[]) T[x].Size+=T[T[x].son[]].Size;
} inline void pushDown(int x) {
if(!T[x].rev) return;
if(T[x].son[]) T[T[x].son[]].rev^=;
if(T[x].son[]) 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];
int rx=T[y].son[]==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);
if(goal==) root=x;
} int Select(int pos, int goal) {
int u=root;
pushDown(u);
while(T[T[u].son[]].Size!=pos) {
if(T[T[u].son[]].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) {
int u=Select(L-, ), v=Select(R+, u);
int x=T[v].son[];
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) {
int u=Select(L-, ), v=Select(R+, u);
T[T[v].son[]].rev^=;
} void DFS(int u) {
pushDown(u);
if(T[u].son[]) DFS(T[u].son[]);
ans.push(T[u].val);
if(T[u].son[]) DFS(T[u].son[]);
} void Display(int n) {
while(!ans.empty()) ans.pop();
DFS(root);
for(int cnt=, x; cnt<n; cnt++, ans.pop()) {
for(x=ans.front(); x==-INF; ans.pop(), x=ans.front());
printf("%d", x);
if(cnt+==n) printf("\n");
else printf(" ");
}
} int build(int L, int R) {
if(L>R) return ;
if(L==R) return L;
int mid=(L+R)>>, 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);
for(int i=; i<=n+; i++) T[i].init(i-);
root=build(, n+);
T[].Size=, T[].son[]=root, fa[root]=, fa[]=;
}
} hehe;
int n, m;
char cmd[]; int main() {
// freopen("in", "r", stdin);
while(scanf("%d%d",&n, &m), n!=- || m!=-) {
hehe.init(n);
for(int i=, a, b, c; i<m; i++) {
scanf("%s", cmd);
if(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);
}
return ;
}

HDU 3487

题目链接 & AC 通道

HDU 3487 Play with Chain

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

  1. HDU 3487 Play with Chain (splay tree)

    Play with Chain Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  2. 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 ...

  3. HDU 3478 Play with Chain (Splay树)

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

  4. HDU 1890:Robotic Sort(Splay)

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

  5. HDU 3487 Play with Chain 【Splay】

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

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

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

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

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

  8. 【BZOJ1862】[ZJOI2006]游戏排名系统 (Splay)

    [BZOJ1862][ZJOI2006]游戏排名系统 (Splay) 题面 BZOJ 洛谷 题解 双倍经验题

  9. 【BZOJ1056】[HAOI2008]排名系统(Splay)

    [BZOJ1056][HAOI2008]排名系统(Splay) 题面 BZOJ 洛谷 题解 \(Splay\)随便维护一下就好了,至于名字什么的,我懒得手写哈希表了,直接哈希之后拿\(map\)压. ...

随机推荐

  1. 设置jenkins代理

    http://stackoverflow.com/documentation/jenkins/919/introduction-to-jenkins Natively, Jenkins runs on ...

  2. HTML5 canvas globalCompositeOperation绘图类型讲解

    我们总是将一个图形画在另一个之上,大多数情况下,这样是不够的.比如说,它这样受制于图形的绘制顺序.不过,我们可以利用 globalCompositeOperation 属性来改变这些做法.global ...

  3. 浅谈压缩感知(二十五):压缩感知重构算法之分段正交匹配追踪(StOMP)

    主要内容: StOMP的算法流程 StOMP的MATLAB实现 一维信号的实验与结果 门限参数Ts.测量数M与重构成功概率关系的实验与结果 一.StOMP的算法流程 分段正交匹配追踪(Stagewis ...

  4. atitit.提升2--3倍开发效率--cbb体系的建设..

    atitit.提升开发效率--cbb体系的建设.. #--提升倍数,大概2--3倍.. #---cbb的内容 知识的,expt的,经验的技术的部件的问题库的角度.. #---cbb的层次,tech l ...

  5. jQuery页面滚动监听事件及高级效果插件

    jQuery页面滚动监听事件及高级效果插件 1. One Page scroll (只适用于上下焦点图)http://www.thepetedesign.com/demos/onepage_scrol ...

  6. ADO.NET笔记20160322

    ####ADO.NET ####1 启用sa验证与窗体相关知识     - 启用sa验证     - ShowDialog() ---- ####2 连接字符串     Data Source=服务器 ...

  7. 更改Windows系统的密码之后,SQL Server 2008服务无法启动

    问题:更改Windows操作系统的密码之后,SQL Server 2008服务无法启动. 原因:SQL Server服务需要使用操作系统的某个登录账户. 解决:需要在服务的属性窗口中修改账户密码,然后 ...

  8. 01、手把手Android攻城入门

    1.Android开发环境搭建: Eclipse Java EE IDE + ADT-23.0.6 + android-sdk-21-with-sdk-manager-r23.0.2 (安卓5.0)+ ...

  9. jmap命令(Java Memory Map)(转)

    JDK内置工具使用 一.javah命令(C Header and Stub File Generator) 二.jps命令(Java Virtual Machine Process Status To ...

  10. 从此爱上iOS Autolayout

    转:从此爱上iOS Autolayout 这篇不是autolayout教程,只是autolayout动员文章和经验之谈,在本文第五节友情链接和推荐中,我将附上足够大家熟练使用autolayout的教程 ...