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个元素,反转后添加到排列尾部 分析:用一个可分裂合并的序列来表示整个序列,截取一段可以用两次分裂一次合并实现,粘 ...
随机推荐
- 构建一个基于 Spring 的 RESTful Web Service
本文详细介绍了基于Spring创建一个“hello world” RESTful web service工程的步骤. 目标 构建一个service,接收如下HTTP GET请求: http://loc ...
- 为MyEclipse加入自己定义凝视
非常多时候我们默认的MyEclipse的类凝视是这种,例如以下图 能够通过改动MyEclipse的凝视规则来改变,不但能够改动类的.还能够改动字段.方法等凝视规则,操作方法例如以下 1.针对方法的凝视 ...
- linux 服务器更主板后无法识别网卡处理过程
linux 服务器更主板后无法识别网卡处理过程 服务器故障报修,主板坏,更换主板后无法识别网卡,ifconfig 查看只显示:lo loopback 127.0.0.1. 系统加载网卡驱动后会去读 ...
- 远程连接到Fedora
首先执行以下3点(主要是前两点) 第一: 开启ssh #service sshd restart 第二:关闭防火墙 #service iptables stop 第三:selinux(重启电脑后失效) ...
- .NET基础拾遗(6)特性
1 神马是特性?如何自定义一个特性? (1)特性是什么 特性是一个对象,可以加载到程序集及程序集的对象中,这些对象包括 程序集本身.模块.类.接口.结构.构造函数.方法.方法参数等,加载了特性 ...
- 自定义HttpHandler
1.创建自定义类型 2.继承IHttpHandler接口,并实现 3.配置Web.Config文件,注册类型 4.访问 public class QuickMsgSatisticsHandler : ...
- mongodb 详解 error:10061 由于目标计算机积极拒绝,无法连接解决方法
mongodb下载地址(32位):下载地址 自己选择版本 建立如下与mongodb并行的两个文件夹data和log. 然后建立mongo.config. 在mongo.config配置文件中输入: # ...
- Android-图标
首先需要申明一点,系统图标并不存在于项目资源中,而是存在于设备中. 这就带来一个大问题,界面风格的控制权交到了不同的设备手中.这是我们不愿意看到的. 如何解决这个问题?有两种方法: 1.创建自己的图标 ...
- JAVA与JSON的序列化、反序列化
package com.linkage.app.memcache; import java.util.HashMap;import java.util.Map.Entry; import net.sf ...
- 把python项目部署到centos里
.安装centos VMware9下面安装centos .在centos下面设置共享文件夹为你本地的论坛的代码,然后设置网络为桥接:直接连接到物理网络,赋值网络连接状态 .进入forum_svr.py ...