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 ...
随机推荐
- 一月份实现Adb小程序
As Brian said: According to a post on xda-developers, you can enable ADB over WiFi from the device w ...
- [.NET 4.5] ADO.NET / ASP.NET 使用 Async 和 Await 异步 存取数据库
此为文章备份,原文出处(我的网站) [.NET 4.5] ADO.NET / ASP.NET 使用 Async 和 Await 异步 存取数据库 http://www.dotblogs.com.tw ...
- 【代码】ini 文件读取工具类
using System; using System.Runtime.InteropServices; using System.Text; namespace hrattendance.Common ...
- [terry笔记]物化视图 materialized view基础学习
一.物化视图定义摘录: 物化视图是包括一个查询结果的数据库对像(由系统实现定期刷新数据),物化视图不是在使用时才读取,而是预先计算并保存表连接或聚集等耗时较多的操作结果,这样在查询时大大提高了 ...
- Python脚本控制的WebDriver 常用操作 <十二> send_keys模拟按键输入
下面将使用WebDriver中的send_keys来模拟键盘按键输入 测试用例场景 send_keys方法可以模拟一些组合键操作: ctrl+a ctrl+c ctrl+v 等. 另外有时候我们需要在 ...
- 【C#】 装箱 (boxing) 和拆箱 (unboxing)
目录: 1. 装箱和拆箱 2. 深入理解装箱和拆箱 3. int[] to object[],值类型数组到对象数组的转化 4. 使用泛型减少装箱和拆箱 1. 装箱和拆箱 装箱 就是把“值类型”转换成 ...
- 【转载】MongoDB参数
我们可以通过mongod --help查看mongod的所有参数说明,以下是各参数的中文解释. 基本配置–quiet# 安静输出 –port arg# 指定服务端口号,默认端口27017 –bind_ ...
- hdu 5154 Harry and Magical Computer
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5154 Harry and Magical Computer Description In reward ...
- 使用AnkhSvn-2.5.12478.msi管理vs2013代码的工具安装步骤使用
安装好AnkhSvn后,按照上面红色画出来的图,进行操作: 需要安装的文件有: AnkhSvn-2.5.12478.msi LanguagePack_1.8.5.25224-x64-zh_CN.msi ...
- 6 让我们的C#程序开始做点数学运算
请相信我你只需要懂得最基本的数学运算,就可以从事大多数的软件项目的开发工作.千万不要一提编程,就让数学把你吓跑了.大多数的程序开发人员从事的编程工作是应用系统的开发.这些系统的绝大多数功能,只需要最基 ...