hdu 3487 Play with Chain
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3487
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?
///*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的更多相关文章
- HDU 3487 Play with Chain(Splay)
题目大意 给一个数列,初始时为 1, 2, 3, ..., n,现在有两种共 m 个操作 操作1. CUT a b c 表示把数列中第 a 个到第 b 个从原数列中删除得到一个新数列,并将它添加到新数 ...
- HDU 3487 Play with Chain | Splay
Play with Chain Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- 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 ...
- HDU 3487 Play with Chain 【Splay】
1-n的序列,有两种操作: 1,将一段区间翻转 2,将一段区间切下来放到剩余序列的第C个数后 采用延迟更新的方法维护区间的翻转,并维护一个size域. 添加一个最大点和一个最小点,防止出界 翻转时,将 ...
- Hdu 3487 play the chain
Description 瑶瑶很喜欢玩项链,她有一根项链上面有很多宝石,宝石从1到n编号. 首先,项链上的宝石的编号组成一个序列:1,2,3,...,n. 她喜欢两种操作: 1.CUT a b c:他会 ...
- 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 ...
- 【HDU 3487】Play with Chain Splay
题意 给定$n$个数序列,每次两个操作,将区间$[L,R]$拼接到去掉区间后的第$c$个数后,或者翻转$[L,R]$ Splay区间操作模板,对于区间提取操作,将$L-1$ Splay到根,再将$R+ ...
- Play with Chain 【HDU - 3487】【Splay+TLE讲解】
题目链接 很好的一道题,用了三天多的时间,终于知道了我为什么T的原因,也知道了在Splay的同时该怎样子的节约时间,因为Splay本身就是大常数的O(N*logN),我们如果不在各种细节上节约时间,很 ...
- 【HDU 5233】Tree chain problem (树形DP+树剖+线段树|树状数组)最大权不相交树链集
[题目] Tree chain problem Problem Description Coco has a tree, whose vertices are conveniently labeled ...
随机推荐
- C#中常见的委托(Func委托、Action委托、Predicate委托)
今天我要说的是C#中的三种委托方式:Func委托,Action委托,Predicate委托以及这三种委托的常见使用场景. Func,Action,Predicate全面解析 首先来说明Func委托,通 ...
- 【转】 BSS段 数据段 代码段 堆栈 指针 vs 引用
原文:http://blog.csdn.net/godspirits/article/details/2953721 BSS段 数据段 代码段 堆栈 (转+) 声明:大部分来自于维基百科,自由的百科全 ...
- 第五章 管理程序流(In .net4.5) 之 异常处理
1. 概述 本章包括.net4.5中异常处理相关的部分. 2. 主要内容 2.1 处理异常 ① try.cahtch.finally 机制,无需多言. ② 使用 Environment.FailFas ...
- pure css做的pc登陆界面
源码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...
- MVC中用ajax提交json对象数组
应用场景:在前端用ajax向服务器提交json对象数组,在controller的以对象数组作为函数的参数,提交的json数组直接转为服务器端的对象数组. 如: 要将json对象数组[{Id:1,Nam ...
- Moses更改权重的命令变化 -d -t -
-l 可以用: weight-l 或者lm (不需要在前面加-) 还是用-weight-overwrite “Distortion0= 0"更保险 reording weight i ...
- 刀哥多线程之gcd-01-sync&async
同步 & 异步 概念 同步 必须等待当前语句执行完毕,才会执行下一条语句 异步 不用等待当前语句执行完毕,就可以执行下一条语句 NSThread 中的 同步 & 异步 - (void) ...
- Android--启动系统的剪切图像功能并返回结果
直接上代码: //启动裁剪图片 private void cropPhotoUri(Uri uri){ Intent intent = new Intent("com.android.cam ...
- hdu 4255 A Famous Grid
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4255 A Famous Grid Description Mr. B has recently dis ...
- swift学习(二)--基本运算符、字符串、集合操作
在这一篇博客里面,我想要介绍一下swift里面一些常用的基本运算符,还有涉及到的字符串,集合操作.你会发现在swift里面还是有许多其他语言所不具有的特性运算操作的. 首先最基本的+,-,*,/,&g ...