洛谷 P3391 模板Splay
#include<bits/stdc++.h>
using namespace std;
#define maxn 200000
int read()
{
char ch=getchar();int f=,w=;
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch<=''&&ch>=''){w=w*+ch-'';ch=getchar();}
return f*w;
} int n,root,m,tot; struct sj
{
int ch[]; //左儿子和右儿子
int ff,v; //ff是父亲 v
int size; //size是儿子节点个数
int mark; //打上的标记
void init(int x,int fa) //初始化一个节点 左儿子和右儿子以及父亲都清零
{
ff=ch[]=ch[]=;
size=;v=x;ff=fa; //含有子节点个数为1 父亲节点为参数fa
}
}t[maxn]; inline void pushup(int x)
{
t[x].size=t[t[x].ch[]].size+t[t[x].ch[]].size+;
} inline void pushdown(int x)
{
if(t[x].mark)
{
t[t[x].ch[]].mark^=;
t[t[x].ch[]].mark^=;
t[x].mark=;
swap(t[x].ch[],t[x].ch[]);
}
} inline void rotate(int x) //旋转函数
{
int y=t[x].ff;
int z=t[y].ff; //这是爷爷节点
int k=t[y].ch[]==x; //看x是左儿子还是右儿子 k取0,1
t[z].ch[t[z].ch[]==y]=x; //这是把爷爷节点的左/右儿子变成x
t[x].ff=z;
t[y].ch[k]=t[x].ch[k^];
t[t[x].ch[k^]].ff=y;
t[x].ch[k^]=y;
t[y].ff=x; //此段画图理解
pushup(y);pushup(x); //再继续进行修改 push_up();
} inline void splay(int x,int goal)
{
while(t[x].ff!=goal) //当我的这个节点还没有达到目标位置
{
int y=t[x].ff;int z=t[y].ff;
if(z!=goal) //如果还没有跳到目标节点 继续旋转
(t[z].ch[]==y)^(t[y].ch[]==x)?rotate(x):rotate(y); //Warning:: !!!!同边现象时要先翻爸爸再翻儿子 否则不满足搜索树的性质!!!!
rotate(x);
}
if(goal==)root=x; //如果目标节点是0 那么就把root 根节点变成x
} inline void insert(int x)
{
int u=root,ff=; //从根节点开始插入 一开始父亲变成0
while(t[u].size!=)ff=u,u=t[u].ch[x>t[u].v]; //有根的时候 ff父亲变成根节点 u再继续下去向下操作
u=++tot; //tot是实时增加的一个记录子节点个数的全局变量
if(ff)t[ff].ch[x>t[ff].v]=u; //如果父亲不为零 他的父亲的左/右儿子就是u
t[u].init(x,ff); //初始化这个节点 并且它的父亲就是ff
splay(u,); //把这个点旋转到根节点
} inline int get_k(int k)
{
int u=root;
while()
{
pushdown(u);
if(t[t[u].ch[]].size>=k)u=t[u].ch[];
else if(t[t[u].ch[]].size+==k)return u;
else k-=t[t[u].ch[]].size+,u=t[u].ch[];
}
} void write(int u)
{
pushdown(u); //最后输出之前先push_down一遍
if(t[u].ch[])write(t[u].ch[]); //先读左儿子
if(t[u].v>&&t[u].v<n+)printf("%d ",t[u].v-);
if(t[u].ch[])write(t[u].ch[]);
} inline void work(int l,int r) //工作函数
{
l=get_k(l);
r=get_k(r+);
splay(l,);
splay(r,l);
t[t[t[root].ch[]].ch[]].mark^=;
} int main()
{
n=read();m=read(); //n个点 m次翻转
for(int i=;i<=n+;++i)insert(i); //跳过建树 直接插入即可 再继续看insert()
for(int i=;i<=m;i++)
{
int l=read(),r=read();
work(l,r); //工作函数
}
write(root); //输出;
return ; //大工告吉
}
洛谷 P3391 模板Splay的更多相关文章
- 洛谷 P3391 【模板】文艺平衡树(Splay)
题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1, ...
- 【阶梯报告】洛谷P3391【模板】文艺平衡树 splay
[阶梯报告]洛谷P3391[模板]文艺平衡树 splay 题目链接在这里[链接](https://www.luogu.org/problemnew/show/P3391)最近在学习splay,终于做对 ...
- [洛谷P3391] 文艺平衡树 (Splay模板)
初识splay 学splay有一段时间了,一直没写...... 本题是splay模板题,维护一个1~n的序列,支持区间翻转(比如1 2 3 4 5 6变成1 2 3 6 5 4),最后输出结果序列. ...
- 洛谷P3391文艺平衡树(Splay)
题目传送门 转载自https://www.cnblogs.com/yousiki/p/6147455.html,转载请注明出处 经典引文 空间效率:O(n) 时间效率:O(log n)插入.查找.删除 ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- BZOJ3224/洛谷P3391 - 普通平衡树(Splay)
BZOJ链接 洛谷链接 题意简述 模板题啦~ 代码 //普通平衡树(Splay) #include <cstdio> int const N=1e5+10; int rt,ndCnt; i ...
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
- BZOJ3223/洛谷P3391 - 文艺平衡树
BZOJ链接 洛谷链接 题意 模板题啦~2 代码 //文艺平衡树 #include <cstdio> #include <algorithm> using namespace ...
- 洛谷P3375 [模板]KMP字符串匹配
To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果 ...
随机推荐
- ubuntu 使用apt命令时报错 E: Could not get lock /var/lib/dpkg/lock - open...
问题描述: 刚刚安装好Ubuntu16.04.使用apt命令时,提示报错信息: abc@pc:~$ sudo apt-get install openssh-server E: Could not g ...
- flask 快速入门链接
http://docs.jinkan.org/docs/flask/quickstart.html
- selenium--iframe
前戏 很多人在用selenium定位页面元素的时候会遇到定位不到的问题,明明元素就在那儿,用firebug也可以看到,就是定位不到,这种情况很有可能是frame在搞鬼. 进入到iframe <h ...
- cocos2dx lua 打印和保存日志
在2d游戏中,经常会出现闪退或者报错的问题,通过写文本,将日志文件发送给服务端,让后端人员进行分析. 通过lua打印日志在文本文件中: local file = io.open(cc.FileUtil ...
- Linux - NodeJS安装
1> 去NodeJS官网 https://nodejs.org/en/ 或 中文网 http://nodejs.cn/download/ 拷贝相应版本的安装文件,如下图: 2> 执行 wg ...
- 【Python学习之五】高级特性2(切片、迭代、列表生成器、生成器、迭代器)
2.迭代 如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration).在Python中,迭代是通过for ... in来完成的. ...
- JQ之$.ajax()方法以及ajax跨域请求
AJAX(Asynchronous javascript AND xml :异步javascript和xml):是一种创建交互式网页应用的网页开发技术.AJAX可以在不重新加载整个页面的情况下与服务器 ...
- 有关git clone 下载速度变慢的解决方法
使用提示:请注意一下,以下方法是在搭有梯子的情况下进行的,也就是说在有梯子的情况下,下载速度始终很慢,使用了以下方法用梯子下载达到正常速度,并没有尝试修复过后不用梯子下载. 所以,如果使用了以下方法, ...
- Python9-网络编程3-day32
解决黏包的问题 #server import socket sk = socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen() conn,addr ...
- Monkey与MonkeyRunner之间的区别
为了支持黑盒自动化测试的场景,Android SDK提供了monkey和monkeyrunner两个测试工具,这两个测试工具除了名字类似外,还都可以向待测应用发送按键等消息,往往容易产生混淆,以下是他 ...