题目大意:给出1到n的有序数列,现在有两个操作:

1.CUT a b c 把第a到第b个数剪切下来,放到剩下的第c个数的后边。

2.FLIP a b  把第a到第b个数反转。

经过总共m次操作后,求现在的数列。

n,m<300000

分析:典型的splay题。包含的操作即:查找第k大,剪切,插入,反转等操作。

维护size,rev(反转标记)即可。

通过size可以找到第k大,通过rev做懒标记,可以进行反转。

具体说就是,比如要剪切CUT a,b,c,以先把第a-1个节点splay到根的位置,然后把第b+1个节点spaly到根的右儿子的位置,则a到b这一段就刚好是根的右儿子的左子树了,然后把它剪切下来。再把第c节点splay到根的位置,把第c+1个节点splay到根的右儿子的位置,再把刚才剪切的那一段接在根的右儿子的左儿子位置即可。FLIP a b的话,先把第a-1个节点splay到根的位置,把第b+1个节点splay到根的右儿子的位置,然后对根的右儿子的左子树打上懒标记即可。注意:打蓝标记应该是tree[i].rev^=1,而不是tree[i].rev=1。我就是这样wa了一次。

因为splay树的伸展特性,splay树中要增加两个额外的虚拟节点,即头节点和尾节点。初始时把头结点作为根节点,把尾节点作为根的右儿子。有效节点作为根的左儿子的右子树。

 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAXN 300505
int tot,root,n,m,a,b,c;
char str[];
struct node
{
int val,fa,sz;
bool rev;
int ch[];
}tree[MAXN];
void newnode(int &r,int father,int val)
{
tot++;
r=tot;
tree[tot].fa=father;
tree[tot].val=val;
}
void build(int &root,int l,int r,int father)
{
if(l>r)return;
int mid=(l+r)/;
newnode(root,father,mid);
build(tree[root].ch[],l,mid-,root);
build(tree[root].ch[],mid+,r,root);
tree[root].sz=tree[tree[root].ch[]].sz+tree[tree[root].ch[]].sz+;
}
void init()
{
tot=root=;
memset(tree,,sizeof tree);
newnode(root,,-);
newnode(tree[root].ch[],root,-);
build(tree[tree[].ch[]].ch[],,n,tree[].ch[]);
tree[tree[].ch[]].sz=tree[tree[tree[].ch[]].ch[]].sz+;
tree[].sz=tree[tree[].ch[]].sz+;
}
void pd(int &r)
{
if(tree[r].rev==)
{swap(tree[r].ch[],tree[r].ch[]);
tree[tree[r].ch[]].rev^=;
tree[tree[r].ch[]].rev^=;
tree[r].rev=;
} }
void pu(int &r)
{
tree[r].sz=tree[tree[r].ch[]].sz+tree[tree[r].ch[]].sz+;
}
void rotato(int &r,bool kind)
{
int y=tree[r].fa;
int yy=tree[y].fa;
if(yy)
{
tree[yy].ch[tree[yy].ch[]==y]=r;
}
tree[r].fa=yy;
tree[tree[r].ch[kind]].fa=y;
tree[y].ch[!kind]=tree[r].ch[kind];
tree[y].fa=r;
tree[r].ch[kind]=y;
pu(y);
pu(r);
}
void splay(int &r,int goal)
{
while(tree[r].fa!=goal)
{
int y=tree[r].fa;
int yy=tree[y].fa;
if(yy==goal)rotato(r,tree[y].ch[]==r);
else
{
int kind=(tree[y].ch[]==r);
if(tree[yy].ch[kind]==y)
{
rotato(r,kind);
rotato(r,!kind);
}
else
{
rotato(y,kind);
rotato(r,kind);
}
}
}
if(goal==)
root=r;
}
int find(int r,int k)
{
pd(r);
if(tree[tree[r].ch[]].sz==k-)
return r;
else if(tree[tree[r].ch[]].sz>k-)
return find(tree[r].ch[],k);
else return find(tree[r].ch[],k-tree[tree[r].ch[]].sz-);
}
void print(int &r)
{
pd(r);
if(tree[r].ch[])
print(tree[r].ch[]);
if(tree[r].val!=-){printf("%d",tree[r].val);if(tot>)printf(" ");tot--;}
if(tree[r].ch[])
print(tree[r].ch[]);
}
int main()
{ while(scanf("%d%d",&n,&m)&&(n>=&&m>=))
{
init();
for(int i=;i<m;i++)
{
scanf("%s",str);
if(str[]=='C')
{
scanf("%d%d%d",&a,&b,&c);
int x1=find(root,a);
int y1=find(root,b+);
splay(x1,);
splay(y1,root);
int t=tree[tree[root].ch[]].ch[];
tree[tree[root].ch[]].ch[]=;
pu(tree[root].ch[]);
pu(root);
x1=find(root,c+);
y1=find(root,c+);
splay(x1,);
splay(y1,root);
tree[tree[root].ch[]].ch[]=t;
tree[t].fa=tree[root].ch[];
pu(tree[root].ch[]);
pu(root);
}
else
{
scanf("%d%d",&a,&b);
int x=find(root,a);
int y=find(root,b+);
splay(x,);
splay(y,root);
tree[tree[tree[root].ch[]].ch[]].rev^=;
}
}
print(root);
printf("\n");
}
}

HDU3487 play with chain的更多相关文章

  1. HDU--3487 Play with Chain (Splay伸展树)

    Play with Chain Problem Description YaoYao is fond of playing his chains. He has a chain containing ...

  2. HDU3487 Play With Chain [Splay]

    题目传送门 题目描述 Problem Description YaoYao is fond of playing his chains. He has a chain containing n dia ...

  3. HDU3487 Play with Chain splay 区间反转

    HDU3487 splay最核心的功能是将平衡树中的节点旋转到他的某个祖先的位置,并且维持平衡树的性质不变. 两个操作(数组实现) cut l,r, c把[l,r]剪下来放到剩下序列中第c个后面的位置 ...

  4. HDU-3487 Play with Chain Splay tee区间反转,移动

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3487 对于一个数列有两种操作:1.CUT a b c,先取出a-b区间的数,然后把它们放在取出后的第c ...

  5. 【HDU3487】【splay分裂合并】Play with Chain

    Problem Description YaoYao is fond of playing his chains. He has a chain containing n diamonds on it ...

  6. HDU 3487 Play with Chain | Splay

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

  7. hdu3487 splay树

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

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

  9. STM32用JLINK 烧写程序时出现NO Cortex-m device found in JTAG chain现象和解决方案

    现象 CPU: STM32107VC 用JLINK 烧写程序时出现NO Cortex-m device found in JTAG chain 如图无法查找到硬件就是CPU 提示1:NO Cortex ...

随机推荐

  1. 读javascript高级程序设计08-引用类型之Global、Math、String

    一.Global 所有在全局作用域定义的属性和方法,都属于Global对象. 1.URI编码: encodeURI():主要用于对整个URI编码.它不会对本身属于URI的特殊字符进行编码. encod ...

  2. win7任务栏只显示日期不显示年月日

    某一天突然发现笔记本任务栏上的时间显示只剩下了时间,没有了年月日 于是百度 搜到的结果大多是如何设置显示的格式  yyyy-MM-dd 继续搜 终于搜到了正确答案 结果令我瞠目结舌  着实无奈 是因为 ...

  3. Windows Store App 插值动画

    插值动画支持DoubleAnimation.ColorAnimation和PointAnimation类型的动画.其中比较常用的是DoubleAnimation动画,它可以用来控制界面元素的Doubl ...

  4. HttpCache ETag与Last-Modified与Expires

    Last-Modified 是检查一个资源最后修改时间.如果时间过期了则返回资源内容.如果没过期,返回304.当Last-Modified更新了,但是资源本质上没有更新,比如资源是A,Last-Mod ...

  5. python讲一个列表写入excel表中

    连接为http://blog.csdn.net/a491057947/article/details/47614263 http://www.crifan.com/export_data_to_exc ...

  6. git在本地仓库直接使用rm彻底删除文件,服务端还是存在

    本地仓库:A和B 服务器:C 今天在本地仓库A希望删除一个文件test,于是执行以下命令: 1 2 3 4 $ sudo rm test $ git add . $ git commit -m &qu ...

  7. 学习node-formidable

    使用第三方包node-formidable,需要通过Node.js的包管理NPM来安装外部包,我们已安装好的Node.js环境一般都已经默认把NPM安装到机器上,我们可以在cmd下通过命令行在NPM中 ...

  8. HTMl5-canvas 入门级复习

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. E1_1 用邻接矩阵存储有向图,并输出各顶点的出度和入度

    参考书:图论算法理论.实现及应用(北京大学出版社) 输入数据:(test.txt) 程序: /* 邻接矩阵存储有向图 */ #include <cstring> #include < ...

  10. 《JavaScript模式》第4章 函数

    @by Ruth92(转载请注明出处) 第4章:函数 一.JavaScript 中函数的两个重要特征 函数是第一类对象,可以作为带有属性和方法的值以及参数进行传递: 函数提供了局部作用域,而其他大括号 ...