题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3487

YaoYao is fond of playing his chains. He has a chain containing n diamonds on it. Diamonds are numbered from 1 to n.
At first, the
diamonds on the chain is a sequence: 1, 2, 3, …, n.
He will perform two types
of operations:
CUT a b c: He will first cut down the chain from the ath
diamond to the bth diamond. And then insert it after the cth diamond on the
remaining chain.
For example, if n=8, the chain is: 1 2 3 4 5 6 7 8; We
perform “CUT 3 5 4”, Then we first cut down 3 4 5, and the remaining chain would
be: 1 2 6 7 8. Then we insert “3 4 5” into the chain before 5th diamond, the
chain turns out to be: 1 2 6 7 3 4 5 8.

FLIP a b: We first cut down the
chain from the ath diamond to the bth diamond. Then reverse the chain and put
them back to the original position.
For example, if we perform “FLIP 2 6” on
the chain: 1 2 6 7 3 4 5 8. The chain will turn out to be: 1 4 3 7 6 2 5
8

He wants to know what the chain looks like after perform m operations.
Could you help him?

题意:题意比较简单,就给一个数列两种操作:1,CUT a,b,c,在原数列截取区间[a,b](a和b指数列a位置和b位置),然后剩下的数列合并在一起,把截取的区间放在那个数列的c  位置;2,FLIP a b 翻转区间[a,b]。
解法:伸展树+延迟标记。
 ///*hdu 3487*/
///G++ 687ms C++ 609ms
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define inf 0x7fffffff
using namespace std;
const int maxn=*1e6+;
struct Splay_Tree
{
struct Node
{
Node *ch[],*pre; ///节点的左儿子和右儿子,父亲节点
int value,size; ///节点的值和以此节点为根的子树的节点个数
bool rev; ///判断是否需要翻转
}*root,*null,*lb,*rb,node[maxn];
int count;
bool flag;
Node *NewNode(int value,Node *father)///插入新节点
{
///Node *e=node[++count];这样写不行
Node *e=node+(++count);
e->value=value;
e->size=;
e->pre=father;
e->rev=false;
e->ch[]=e->ch[]=null;
return e;
}
void Update(Node *p)///更新节点p的信息
{
if (p==null) return;
p->size=p->ch[]->size + p->ch[]->size + ;
}
void PushDown(Node *x)///向下更新标记
{
if (x==null) return;
if (x->rev)
{
x->rev=false;
Node *t=x->ch[] ;x->ch[]=x->ch[] ;x->ch[]=t;
x->ch[]->rev= !x->ch[]->rev;
x->ch[]->rev= !x->ch[]->rev;
}
}
void Rotate(Node *x,bool d)///右旋转:true;左旋转:false
{
Node *y=x->pre;
y->ch[!d]=x->ch[d];
if (x->ch[d]!=null) x->ch[d]->pre=y;
x->pre=y->pre;
if (y->pre!=null)
{
if (y==y->pre->ch[d])
y->pre->ch[d]=x;
else y->pre->ch[!d]=x;
}
x->ch[d]=y;
y->pre=x;
Update(y);
Update(x);
if (root==y) root=x;
}
void Splay(Node *x,Node *target)///伸展操作
{
PushDown(x);
Node *y;
while (x->pre!=target)
{
y=x->pre;
if (x==y->ch[])
{
if (y->pre!=target && y->pre->ch[]==y)
Rotate(y,true);
Rotate(x,true);
}
else
{
if (y->pre!=target && y->pre->ch[]==y)
Rotate(y,false);
Rotate(x,false);
}
}
Update(x);
}
void Select(int k,Node *y)///选择第k个位置的节点
{
Node *x=root;
PushDown(x);
while (k!=x->ch[]->size+)
{
if (k<=x->ch[]->size)
x=x->ch[];
else
{
k -= x->ch[]->size+;
x=x->ch[];
}
PushDown(x);
}
Splay(x,y);
}
void MakeTree(int l,int r,int *an,Node *p,int side)
{
if (l>r) return;
int mid=(l+r)>>;
Node *x;
x=NewNode(an[mid],p);
p->ch[side]=x;
MakeTree(l,mid-,an,x,);
MakeTree(mid+,r,an,x,);
Update(x);
}
///****///
///在pos后面插入长度为cnt的区间
void Insert(int pos,int cnt,int *an)
{
Select(pos+,null);
Select(pos+,root);
MakeTree(,cnt,an,root->ch[],);
Splay(root->ch[]->ch[],null);
}
///删除pos后长度为cnt的区间
void Delete(int pos,int cnt,int ind)
{
Node *p1;
Select(pos,null);
Select(pos+cnt+,root);
p1=root->ch[]->ch[];
root->ch[]->ch[]=null; Splay(root->ch[],null);
Select(ind+,null);
Select(ind+,root);
root->ch[]->ch[]=p1;
Splay(root->ch[],null);///注意不是Splay(root->ch[1]->ch[0],null)
}
///旋转pos后长度为cnt的区间
void Reverse(int pos,int cnt)
{
Select(pos,null);
Select(pos+cnt+,root);
root->ch[]->ch[]->rev= !root->ch[]->ch[]->rev;
Splay(root->ch[]->ch[],null);
}
void Index(int pos)
{
Select(pos+,null);
printf("%d",root->value);
}
void Out()///调试程序
{
flag=false;
Print(root);///打印整个区间
printf("\n");
}
void Print(Node *now)///打印区间
{
if (now==null) return;
if (now->ch[]==null&&now->ch[]==null)
{
if (now->value!=inf)
{
if (flag) printf(" ");
flag=true;
printf("%d",now->value);
}
return;
}
PushDown(now);
Print(now->ch[]);
if (now->value!=inf)
{
if (flag) printf(" ");
flag=true;
printf("%d",now->value);
}
Print(now->ch[]);
}
void init()
{
count=-;
null=;
null=NewNode(inf,);
null->size=;
lb=root=NewNode(inf,null);
rb=root->ch[]=NewNode(inf,root);
Update(root);
}
}splay;
int an[maxn];
int main()
{
int n,m; char str[];
int a,b,c;
while (scanf("%d%d",&n,&m)!=EOF)
{
if (n< && m<) break;
splay.init();
for (int i= ;i<=n ;i++) an[i]=i;
splay.Insert(,n,an);
while (m--)
{
scanf("%s",str);
if (str[]=='C')
{
scanf("%d%d%d",&a,&b,&c);
splay.Delete(a,b-a+,c);
}
else
{
scanf("%d%d",&a,&b);
splay.Reverse(a,b-a+);
}
}
splay.Out();
}
return ;
}

hdu 3487 Play with Chain的更多相关文章

  1. HDU 3487 Play with Chain(Splay)

    题目大意 给一个数列,初始时为 1, 2, 3, ..., n,现在有两种共 m 个操作 操作1. CUT a b c 表示把数列中第 a 个到第 b 个从原数列中删除得到一个新数列,并将它添加到新数 ...

  2. HDU 3487 Play with Chain | Splay

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

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

  4. HDU 3487 Play with Chain 【Splay】

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

  5. Hdu 3487 play the chain

    Description 瑶瑶很喜欢玩项链,她有一根项链上面有很多宝石,宝石从1到n编号. 首先,项链上的宝石的编号组成一个序列:1,2,3,...,n. 她喜欢两种操作: 1.CUT a b c:他会 ...

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

  7. 【HDU 3487】Play with Chain Splay

    题意 给定$n$个数序列,每次两个操作,将区间$[L,R]$拼接到去掉区间后的第$c$个数后,或者翻转$[L,R]$ Splay区间操作模板,对于区间提取操作,将$L-1$ Splay到根,再将$R+ ...

  8. Play with Chain 【HDU - 3487】【Splay+TLE讲解】

    题目链接 很好的一道题,用了三天多的时间,终于知道了我为什么T的原因,也知道了在Splay的同时该怎样子的节约时间,因为Splay本身就是大常数的O(N*logN),我们如果不在各种细节上节约时间,很 ...

  9. 【HDU 5233】Tree chain problem (树形DP+树剖+线段树|树状数组)最大权不相交树链集

    [题目] Tree chain problem Problem Description Coco has a tree, whose vertices are conveniently labeled ...

随机推荐

  1. 各种数据处理方案(SQL,NoSQL,其他)的应用场景

    综合stackoverflow和linkin上的相关讨论,还有我个人的工作经验:   Redis应用场景(大部分场景下memcache可以用Redis代替,所以不单独讨论) 线上业务,读写的高性能要求 ...

  2. 有趣的EditView为空时的抖动效果(用户名和密码)--第三方开源--ClearEditText

    ClearEditText在github上的链接地址是:https://github.com/zhangphil/ClearEditText 用法十分简单,在布局中使用ClearEditText,在J ...

  3. OVER Clause是个好东西,常和ROW_NUMBER()、Sum、AVG、Count、Min、Max配合使用

    根据SQL官方帮助的实例: USE AdventureWorks2012; GO SELECT ROW_NUMBER() OVER(PARTITION BY PostalCode ORDER BY S ...

  4. DELPHI 使用dbexpress控件连接MySQL数据库方法

    1. 在窗体上放置4个控件: SQLConnection1,SimpleDataSet1,DataSource1,DBGrid (注意: 如果 出现"Operation not allowe ...

  5. SymPy库常用函数

    简介 SymPy是一个符号计算的Python库.它的目标是成为一个全功能的计算机代数系统,同时保持代码简 洁.易于理解和扩展.它完全由Python写成,不依赖于外部库.SymPy支持符号计算.高精度计 ...

  6. javascripy的innerHTML在IE8下的异常

    使用jQuery的datatable插件的时候发现,IE8下显示异常,仔细调查一番,发现是浏览器对innerHTML的差异导致的. 实例代码: var nTd = document.createEle ...

  7. webpack 学习笔记 01 使用webpack的原因

    本系列文章实际上就是官网文档的翻译加上自己实践过程中的理解. 伴随着websites演化至web apps的过程,有三个现象是很明显的: 页面中有越来越多的Js. 客户端能做的事情越来越多. 越来越少 ...

  8. 人脸检测的API例子

    package cliu.TutorialOnFaceDetect; /* * MyImageView.java * Download by http://www.codefans.net * [AU ...

  9. 7.Knockout.Js(Mapping插件)

    前言 Knockout设计成允许你使用任何JavaScript对象作为view model.必须view model的一些属性是observable的,你可以使用KO绑定他们到你的UI元素上,当这些o ...

  10. Swift基础小结_2

    import Foundation // MARK: - ?和!的区别// ?代表可选类型,实质上是枚举类型,里面有None和Some两种类型,其实nil相当于OPtional.None,如果非nil ...