题目链接: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 ;
}

最新文章

  1. 关于Java深clone 的例子学习
  2. Java经典实例:按字符颠倒字符串
  3. Terminating app due to uncaught
  4. Qt中使用随机数
  5. html5 shiv
  6. json2.js 的使用
  7. 拷贝出你GAC里面的DLL文件
  8. ORA-00933 UNION 与 ORDER BY
  9. javascript 中 keyup、keypress和keydown事件
  10. JAVA 对象内存分析
  11. C++设计模式-Visitor访问者模式
  12. cloud-init 工作原理 - 每天5分钟玩转 OpenStack(171)
  13. 计蒜客:百度的科学计算器(简单)【python神解】
  14. ABB机器人基础培训资料整理与总结
  15. render与vue组件和注册
  16. Flask Session 使用和源码分析 —— (6)
  17. week6
  18. 《A Knowledge-Grounded Neural Conversation Model》
  19. 为IE内核的WebBrowser控件内存泄漏所烦恼的可以考虑用Cefsharp代替它!
  20. NETBEAN 启动报错 CANNOT LOCATE JAVA INSTALLATION IN SPECIFIED JDKHOME的解决办法

热门文章

  1. PHP通过IP 获取 地理位置(实例)
  2. PHP截取字符串 兼容utf-8 gb2312
  3. Java实现九九乘法表的输出
  4. Unable to execute dex: java.nio.BufferOverflowException. Check the Eclipse log for stack trace.
  5. 【Windows】如何判断当前鼠标是否按下左键或右键
  6. 对于java反射的理解
  7. Linux 两个目录浅对比拷贝
  8. Python脚本控制的WebDriver 常用操作 &lt;三&gt; 浏览器最大化
  9. equals方法,hashcode()方法
  10. 整齐地输出n的平方,立方