题目大意:给出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. canvas初体验之加载图片

    上一篇的介绍主要是画一些基本的图案,这一篇主要是加载图案. canvas加载图片主要分为两个步骤: 1.获取图片资源. 2.将图片资源画到画布上. 1.1获取图片资源,canvasAPI为我们提供了多 ...

  2. css 浮动

    1. 浮动 浮动是css的布局功能,在CSS中,包括div在内的任何元素都可以浮动的方式显示.它能够改变页面中对象的前后流动顺序.浮动元素会脱离文档流,不占据空间.浮动元素可以左右移动,直到碰到包含它 ...

  3. ASP.NET jquery.uploadify上传控件中文乱码解决办法(转)

    原文地址:http://blog.csdn.net/ningxi_/article/details/6234725 在一般处理程序上加上这几句话: context.Response.ContentTy ...

  4. linux 查看剩余内存数

    返回的是kb的数值 cat /proc/meminfo | grep MemFree | cut -d ":" -f2 | sed -e 's/\(^ *\)//' -e 's/\ ...

  5. sorttable

    http://rubaxa.github.io/Sortable/Sortable.js http://rubaxa.github.io/Sortable/Sortable.min.jshttp:// ...

  6. GSM模块fibocom G510使用记录

    一、背景:最近在做一个单定位的产品,对低功耗要求较高,选用了G510系列的模块。现在仅做了三块样板,先熟悉下。 二、优点:1.功耗低,和西门子的BGS2差不多;2.注册网络指令简单;3.其他有待发现 ...

  7. 分析器错误 MvcApplication 找不到

    <%@ Application Codebehind="Global.asax.cs" Inherits="test.MvcApplication" La ...

  8. MySQL字符集乱码

    学数据库,最让人丧气的就是字符集的问题了,一旦出问题,就会有砸电脑的冲动,特别是在修改很多次字符集后依然不成功的时候! 我用的数据库软件是MySQL 5.1.28.最初出问题的时候,是这样的: 情景一 ...

  9. PCL安装使用

    一. 下载安装 http://pointclouds.org/downloads/windows.html 1. QT安装在默认路径下(否则后续会出现问题),添加环境变量QTDIR(c:\Qt\4.8 ...

  10. .NET 强引用和弱引用

    一:什么是弱引用 了解弱引用之前,先了解一下什么是强引用 例如 : Object obj=new Object();     就是一个强引用,内存分配一份空间给用以存储Object数据,这块内存有一个 ...