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个元素,反转后添加到排列尾部 分析:用一个可分裂合并的序列来表示整个序列,截取一段可以用两次分裂一次合并实现,粘 ...
随机推荐
- User Defined Runtime Attributes
设置View borderWidth/cornerRadius/borderColor 为了兼容CALayer 的KVC ,你得给CALayer增加一个分类 CALayer+BorderColor.h ...
- RPG JS跨平台测试
RPG JS虽然说是跨平台的,但是在具体的测试中效果并不理想. 以官方提供的Demo为例 问题一 手机的屏幕太小,导致画面上的人物都很小,连点击都很不准确.在9寸的平板上才可以看得比较清楚. 问题二 ...
- Ubuntu 14.04根据系统,休眠后不能启动要解决的问题
简介: 提升Ubuntu制度14.04之后,当系统进入休眠,我们不能再次启动,直接崩溃,凡出了问题? 1. 问题纳入 Ubuntu升级系统14.04之后.通过系统的Power设置休眠时间,在系统进 ...
- Javascript高级程序设计读书笔记(第二章)
第二章 在HTML中使用Javascript 2.1<script>元素 延迟脚本(defer = "defer")表明脚本在执行时不会影响页面的构造,脚本会被延迟到 ...
- (转)IIS7 下部署Asp.net应用
最近在部署一个ASP.NET的应用到IIS7中的时候,遇到了一些问题,现在把部署中的遇到的问题和部署步骤进行总结一下,本文中只涉及到ASP.NET的基本部署. 一. 部署环境 Windows 7 ...
- java二维不定长数组测试
package foxe; import javax.swing.JEditorPane;import javax.swing.JFrame; /** * @author fooxe * * @see ...
- Js得到radiobuttonlist选中值,设置默认值
JS 代码 var vRbtid=document.getElementById("rbtid"); //得到所有radio var vRbtidList= v ...
- BZOJ 3277 串 (广义后缀自动机)
3277: 串 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 309 Solved: 118 [Submit][Status][Discuss] De ...
- C++中explicit
[explicit] 1.用于抑制隐式转换,即: X x = ; // error X x(); // ok 2.只对一个实参的构造函数有效,但是,可以用多有多个实参的构造函数,目前没有意义: cla ...
- Bootstrap学习笔记(未整理)
强调class 这些class通过颜色来表示强调.也可以应用于链接,当鼠标盘旋于链接上时,其颜色会变深,就像默认的链接样式. <p class="text-muted"> ...