Hdu3487-Play with Chain(伸展树分裂合并)
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?
For each test case, the first line contains two numbers: n and m (1≤n, m≤3*100000), indicating the total number of diamonds on the chain and the number of operations respectively. Then m lines follow, each line contains one operation. The command is like this: CUT a b c // Means a CUT operation, 1 ≤ a ≤ b ≤ n, 0≤ c ≤ n-(b-a+1). FLIP a b // Means a FLIP operation, 1 ≤ a < b ≤ n. The input ends up with two negative numbers, which should not be processed as a case.
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int INF=1e9+;
const int maxn=;
int N,M,ans,A[maxn],cnt; //A数组保存数,cnt是节点标号,我是用数组模拟的
struct treap
{
treap* son[]; //左右儿子
int v,s,rev;
treap(){ v=s=rev=; son[]=son[]=NULL; }
treap(int nv);
int rk(){ return son[]->s+; } //排名,第几个数
int cmp(int k) //比较,如果相等返回-1,小于返回0,大于1
{
if(k==rk()) return -;
return k<rk()?:;
}
void pushup(){ s=son[]->s+son[]->s+; } //更新大小
void pushdown(); //处理懒惰标记
}null,tr[maxn];
treap::treap(int nv)
{
v=nv;
s=;
rev=;
son[]=son[]=&null;
}
void treap::pushdown()
{
if(this==&null) return;
if(rev)
{
swap(son[],son[]);
son[]->rev^=;
son[]->rev^=;
rev=;
}
}
treap* NewNode(int x)
{
tr[cnt]=treap(x);
return tr+cnt++;
}
struct splaytree
{
int Size;
treap* root;
splaytree(){ Size=; root=&null; }
void Rotate(treap* &t,int d) //翻转操作
{
t->pushdown();
treap* p=t->son[d^];
p->pushdown();
t->son[d^]=p->son[d];
p->son[d]=t;
t->pushup();
t=p;
t->pushup();
}
void Splay(treap* &t,int k) //将第k大的节点伸展到根
{
t->pushdown();
int d=t->cmp(k);
if(d!=-)
{
if(d) Splay(t->son[d],k- t->rk());
else Splay(t->son[d],k);
Rotate(t,d^);
}
t->pushup();
}
void Build(treap* &t,int le,int ri) //将N个数建成一棵树
{
if(le>ri) return;
int mid=(le+ri)/;
t=NewNode(mid);
Build(t->son[],le,mid-);
Build(t->son[],mid+,ri);
t->pushup();
}
void Cut(treap* &t,int a,int b,int c)
{
int len=b-a+;
if(len==N) return; //是整个区间就不用管了
Splay(t,a); t->pushdown(); //分裂出左边的
treap *L=t->son[];
L->pushdown();
t->son[]=&null; t->pushup(); Splay(t,len); t->pushdown(); //分裂出右边的
treap *R=t->son[];
R->pushdown();
t->son[]=&null; t->pushup(); treap *nt;
if(R!=&null) //左右合并
{
nt=R;
Splay(nt,);
nt->son[]=L; nt->pushup();
}
else
{
nt=L;
Splay(nt,a-);
nt->son[]=R; nt->pushup();
}
if(c+len==N) //在整个之后特殊处理一下就好
{
Splay(nt,c);
Splay(t,);
t->son[]=nt;
t->pushup();
return;
}
Splay(nt,c+);
treap *l=nt->son[]; l->pushdown();
nt->son[]=&null; nt->pushup();
t->son[]=nt; t->pushup();
Splay(t,);
t->son[]=l; t->pushup();
}
void Reverse(treap* &t,int a,int b) //翻转
{
Splay(t,a); //左边
treap *L=t->son[];
L->pushdown();
t->son[]=&null; t->pushup();
Splay(t,b-a+); //右边
treap *R=t->son[];
R->pushdown();
t->son[]=&null; t->pushup();
t->rev^=; //置翻转标记
t->pushdown();
t->son[]=L; t->pushup();
Splay(t,b);
t->son[]=R; t->pushup();
}
void PushAll(treap* &t) //中序遍历
{
if(t==&null) return;
t->pushdown();
PushAll(t->son[]);
A[++ans]=t->v;
PushAll(t->son[]);
t->pushup();
}
};
int main()
{
while(scanf("%d%d",&N,&M)!=EOF)
{
if(N<&&M<) break;
splaytree spt; cnt=;
spt.Build(spt.root,,N); //建树
int a,b,c;
char op[];
while(M--)
{
scanf("%s",op);
if(op[]=='C') //CUT操作
{
scanf("%d%d%d",&a,&b,&c);
spt.Cut(spt.root,a,b,c);
}
else //FLIP操作
{
scanf("%d%d",&a,&b);
spt.Reverse(spt.root,a,b);
} }
ans=;
spt.PushAll(spt.root); //整个下压
for(int i=;i<=ans;i++)
printf("%d%c",A[i],i==ans?'\n':' ');
}
return ;
}
Hdu3487-Play with Chain(伸展树分裂合并)的更多相关文章
- [HEOI2016/TJOI2016] 排序 解题报告(二分答案/线段树分裂合并+set)
题目链接: https://www.luogu.org/problemnew/show/P2824 题目描述: 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在 ...
- 有趣的线段树模板合集(线段树,最短/长路,单调栈,线段树合并,线段树分裂,树上差分,Tarjan-LCA,势能线段树,李超线段树)
线段树分裂 以某个键值为中点将线段树分裂成左右两部分,应该类似Treap的分裂吧(我菜不会Treap).一般应用于区间排序. 方法很简单,就是把分裂之后的两棵树的重复的\(\log\)个节点新建出来, ...
- [BZOJ4552][TJOI2016&&HEOI2016]排序(二分答案+线段树/线段树分裂与合并)
解法一:二分答案+线段树 首先我们知道,对于一个01序列排序,用线段树维护的话可以做到单次排序复杂度仅为log级别. 这道题只有一个询问,所以离线没有意义,而一个询问让我们很自然的想到二分答案.先二分 ...
- Splay 伸展树
废话不说,有篇论文可供参考:杨思雨:<伸展树的基本操作与应用> Splay的好处可以快速分裂和合并. ===============================14.07.26更新== ...
- [SinGuLaRiTy] SplayTree 伸展树
[SinGuLaRiTy-1010]Copyrights (c) SinGuLaRiTy 2017. All Rights Reserved. Some Method Are Reprinted Fr ...
- Splay伸展树入门(单点操作,区间维护)附例题模板
Pps:终于学会了伸展树的区间操作,做一个完整的总结,总结一下自己的伸展树的单点操作和区间维护,顺便给未来的自己总结复习用. splay是一种平衡树,[平均]操作复杂度O(nlogn).首先平衡树先是 ...
- K:伸展树(splay tree)
伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它能在O(lgN)内完成插入.查找和删除操作.在伸展树上的一般操作都基于伸展操作:假设想要对一个二叉查找树执行一系列的查找操作,为了使 ...
- wikioi 1396 伸展树(两个模板)
题目描写叙述 Description Tiger近期被公司升任为营业部经理.他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来 ...
- UVA 11922 Permutation Transformer —— splay伸展树
题意:根据m条指令改变排列1 2 3 4 … n ,每条指令(a, b)表示取出第a~b个元素,反转后添加到排列尾部 分析:用一个可分裂合并的序列来表示整个序列,截取一段可以用两次分裂一次合并实现,粘 ...
随机推荐
- 上传图片代码(chuantouxiang.php+touxiangchuli.php)
<body> <form action="touxiangchuli.php" method="post" enctype="mul ...
- Spring初学(一)
Spring核心机制:依赖注入 依赖注入简单的理解就是 由Spring负责对model进行设置,而非由controller直接设置. 通过依赖注入,javaEE各种组件可以解耦. 依赖注入(Depen ...
- HDU 2689 sort it - from lanshui_Yang
Problem Description You want to processe a sequence of n distinct integers by swapping two adjacent ...
- Android BLE开发之Android手机与BLE终端通信
本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处! 近期穿戴设备发展得非常火.把相关技术也带旺了,当中一项是BLE(Bluetooth Low Energy).B ...
- linux系统下怎么安装.deb文件?
linux系统下怎么安装.deb文件? deb 是 ubuntu .debian 的格式. rpm 是 redhat .fedora .suse 的格式. 他们不通用(尽管能够转换一下). deb是d ...
- Pig系统分析(6)-从Physical Plan到MR Plan再到Hadoop Job
从Physical Plan到Map-Reduce Plan 注:由于我们重点关注的是Pig On Spark针对RDD的运行计划,所以Pig物理运行计划之后的后端參考意义不大,这些部分主要分析流程, ...
- compareTo简介
compareTo()方法是用来比较字符串大小,该方法用来判断一个字符串是大于,等于还是小于另一个字符串.判断字符串大小的依据是根据他们在字典中的顺序决定的 语法 Str1.compareTo(Str ...
- java基础之反射
反射的定义,反射的特性,反射的应用
- 小结: Async & Await
新项目组用到Async & Await, 关于Await会不会新开不开线程,遇到什么情况会新开线程的问题网上查了很多资料都没看到直观的解释.现简单总结一下. 直接上代码: namespace ...
- css Reset文件
/* KISSY CSS Reset 理念:清除和重置是紧密不可分的 特色:1.适应中文 2.基于最新主流浏览器 维护:玉伯(lifesinger@gmail.com), 正淳(ragecarrier ...