bzoj4825 [Hnoi2017]单旋
Description

Input
Output
Sample Input
1 2
1 1
1 3
4
5
Sample Output
1
2
2
2
2
正解:$link-cut \ tree+set$
这题我能说什么。。考场上没想到,然而考后就想出来了。。
其实这题是一道大水题吧。。其实连$LCT$都不要用,直接线段树维护就行了。。
我们可以观察得到:插入结点时一定是插到它的前驱或后继中深度更深的那个下面。
单旋最值其实就是把最值抽出来,与原来的根相连,然后再把它的子树与它原来的父亲相连。删除操作类似,还简单一些。。
然后我们直接用$LCT$维护$spaly$。插入,单旋,删除的时候各种$link$,$cut$就行了,顺便再开两个数组维护一下原树的父子关系。
同时我们要查询前驱,后继,最小值,最大值,这个用$set$就能很方便地解决。
每次查询深度,就是$makeroot$一下树根,然后$access$并$splay$当前点,直接查询$splay$中子树大小就行了。
注意细节:如果单旋的时候这个点已经是根就不要$link$,$cut$了。这个地方坑了我好久。。
//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1<<30)
#define N (100010)
#define ls (x<<1)
#define rs (x<<1|1)
#define il inline
#define RG register
#define ll long long
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) using namespace std; set <int> tr;
set <int>::iterator r; struct data{ int c,k; }q[N]; int hsh[N],rev[N],sz[N],st[N],fa[N],ch[N][],f[N],c[N][],m,rt,cnt,tot; il int gi(){
RG int x=,q=; RG char ch=getchar();
while ((ch<'' || ch>'') && ch!='-') ch=getchar();
if (ch=='-') q=-,ch=getchar();
while (ch>='' && ch<='') x=x*+ch-,ch=getchar();
return q*x;
} il int isroot(RG int x){
return ch[fa[x]][]!=x && ch[fa[x]][]!=x;
} il void pushdown(RG int x){
rev[x]=,rev[ch[x][]]^=,rev[ch[x][]]^=;
swap(ch[x][],ch[x][]); return;
} il void pushup(RG int x){
sz[x]=sz[ch[x][]]+sz[ch[x][]]+; return;
} il void rotate(RG int x){
RG int y=fa[x],z=fa[y],k=ch[y][]==x;
if (!isroot(y)) ch[z][ch[z][]==y]=x;
fa[x]=z,ch[y][k^]=ch[x][k],fa[ch[x][k]]=y;
ch[x][k]=y,fa[y]=x,pushup(y),pushup(x); return;
} il void splay(RG int x){
RG int top=; st[++top]=x;
for (RG int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i];
for (RG int i=top;i;--i) if (rev[st[i]]) pushdown(st[i]);
while (!isroot(x)){
RG int y=fa[x],z=fa[y];
if (!isroot(y)){
if ((ch[z][]==y)^(ch[y][]==x)) rotate(x);
else rotate(y);
}
rotate(x);
}
return;
} il void access(RG int x){
RG int t=;
while (x){
splay(x),ch[x][]=t;
pushup(x),t=x,x=fa[x];
}
return;
} il void makeroot(RG int x){
access(x),splay(x),rev[x]^=; return;
} il void link(RG int x,RG int y){
if (!x || !y || x==y) return;
makeroot(x),fa[x]=y; return;
} il void cut(RG int x,RG int y){
if (!x || !y || x==y) return;
makeroot(x),access(y),splay(y);
fa[x]=ch[y][]=,pushup(y); return;
} il int query(RG int x){
makeroot(rt),access(x),splay(x);
return sz[x];
} il void update1(RG int x,RG int k){
RG int y=f[x],z=c[x][k];
c[x][k]=rt,f[rt]=x,f[x]=;
c[y][k^]=z,f[z]=y; return;
} il void update2(RG int x,RG int k){
RG int y=f[x],z=c[x][k]; if (x==rt) rt=z;
c[y][k^]=z,f[z]=y,c[x][k]=f[x]=; return;
} il void work(){
m=gi(),tr.insert(-inf),tr.insert(inf);
for (RG int i=;i<=m;++i){
q[i].c=gi(),sz[i]=;
if (q[i].c==) q[i].k=gi(),hsh[++tot]=q[i].k;
}
sort(hsh+,hsh+tot+),tot=unique(hsh+,hsh+tot+)-hsh-;
for (RG int i=;i<=m;++i){
if (q[i].c==){
q[i].k=lower_bound(hsh+,hsh+tot+,q[i].k)-hsh;
if (!cnt) tr.insert(rt=q[i].k),++cnt,puts(""); else{
r=tr.upper_bound(q[i].k); RG int nxt=*r,x=,d=,k; --r; RG int pre=*r;
if (pre!=-inf){ k=query(pre); if (d<k) x=pre,d=k; }
if (nxt!=inf){ k=query(nxt); if (d<k) x=nxt,d=k; }
f[q[i].k]=x,c[x][x<q[i].k]=q[i].k,link(x,q[i].k);
++cnt,tr.insert(q[i].k),printf("%d\n",d+);
}
}
if (q[i].c==){
if (cnt==) puts(""); else{
r=tr.begin(),++r; RG int x=*r,y=f[x],z=c[x][],k=query(x);
if (x!=rt) cut(x,y),cut(x,z),link(x,rt),link(y,z),update1(x,),rt=x;
printf("%d\n",k);
}
}
if (q[i].c==){
if (cnt==) puts(""); else{
r=tr.end(),--r,--r; RG int x=*r,y=f[x],z=c[x][],k=query(x);
if (x!=rt) cut(x,y),cut(x,z),link(x,rt),link(y,z),update1(x,),rt=x;
printf("%d\n",k);
}
}
if (q[i].c==){
if (cnt==) puts(""),tr.erase(tr.find(rt)),rt=,--cnt; else{
r=tr.begin(),++r; RG int x=*r,y=f[x],z=c[x][],k=query(x);
tr.erase(tr.find(x)),--cnt,cut(x,y),cut(x,z),link(y,z);
update2(x,),printf("%d\n",k);
}
}
if (q[i].c==){
if (cnt==) puts(""),tr.erase(tr.find(rt)),rt=,--cnt; else{
r=tr.end(),--r,--r; RG int x=*r,y=f[x],z=c[x][],k=query(x);
tr.erase(tr.find(x)),--cnt,cut(x,y),cut(x,z),link(y,z);
update2(x,),printf("%d\n",k);
}
}
}
return;
} int main(){
File("splay");
work();
return ;
}
bzoj4825 [Hnoi2017]单旋的更多相关文章
- [BZOJ4825][HNOI2017]单旋(线段树+Splay)
4825: [Hnoi2017]单旋 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 667 Solved: 342[Submit][Status][ ...
- BZOJ4825: [Hnoi2017]单旋(Splay)
题面 传送门 题解 调了好几个小时--指针太难写了-- 因为只单旋最值,我们以单旋\(\min\)为例,那么\(\min\)是没有左子树的,而它旋到根之后,它的深度变为\(1\),它的右子树里所有节点 ...
- BZOJ4825 [Hnoi2017]单旋 【线段树】
题目链接 BZOJ4825 题解 手模一下操作,会发现一些很优美的性质: 每次旋到根,只有其子树深度不变,剩余点深度\(+1\) 每次旋到根,[最小值为例]右儿子接到其父亲的左儿子,其余点形态不改变, ...
- [BZOJ4825][HNOI2017]单旋spaly
BZOJ Luogu 题目太长了,就不放了. 题解 首先声明一点,无论是splay还是spaly,插入一个新的元素,都要rotate到根!所以说题目也算是给了一个错误示范吧. 我们发现把最值旋转到根并 ...
- 【BZOJ4825】[Hnoi2017]单旋 线段树+set
[BZOJ4825][Hnoi2017]单旋 Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能 ...
- bzoj 4825: [Hnoi2017]单旋 [lct]
4825: [Hnoi2017]单旋 题意:有趣的spaly hnoi2017刚出来我就去做,当时这题作死用了ett,调了5节课没做出来然后发现好像直接用lct就行了然后弃掉了... md用lct不知 ...
- 【LG3721】[HNOI2017]单旋
[LG3721][HNOI2017]单旋 题面 洛谷 题解 20pts 直接模拟\(spaly\)的过程即可. 100pts 可以发现单旋最大.最小值到根,手玩是有显然规律的,发现只需要几次\(lin ...
- 4825: [Hnoi2017]单旋
4825: [Hnoi2017]单旋 链接 分析: 以后采取更保险的方式写代码!!!81行本来以为不特判也可以,然后就总是比答案大1,甚至出现负数,调啊调啊调啊调~~~ 只会旋转最大值和最小值,以最小 ...
- 【bzoj4825】[Hnoi2017]单旋 线段树+STL-set
题目描述 H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必修技能.有一天 ...
随机推荐
- 简易漫画网站搭建-漫画喵Server版
小喵的唠叨话:寒假的时候写了一个漫画爬虫,爬取了好几个漫画,不过一直没有找到合适的漫画阅读的工具.因此最近就试着自己写一个漫画的网站,放在公网上或者局域网里,这样就能随时随地用手机.Pad看漫画了. ...
- php文件基本操作与文件管理功能
文件的基本操作 先来看一下PHP文件基础操作,请看强大注释 <body> <?php var_dump(filetype("./img/11.png")); // ...
- 解决Antimalware Service Executable CPU占用高听语音
windows8/8.1,WIN10自带的安全软件Windows defender还不错,基本可以不用装其他杀毒软件了. 但是其进程Antimalware Service Executable 出现C ...
- Android设计模式之代理模式
代理模式: 为其他对象提供一种代理以控制对这个对象的访问 Subject类定义了RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy inte ...
- Android中的ScrollTo和ScrollBy解析
关于Android中的ScrollBy和ScrollTo方法相信大家并不陌生,这两个方法是在View中实现的.所以在各个继承了View的类都可以使用改方法. 在View中对这两个方法的源码编写是这样的 ...
- 解决在eclipse中写ImageView时有警告的问题
Eclipse中写了一个android程序其中main.xml中ImageView哪行是个黄叹号!不知道为什么? 解决办法: android:contentDescription="@str ...
- C#封装MongoDB工具类库
什么是MongoDB MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统. 在高负载的情况下,添加更多的节点,可以保证服务器性能. MongoDB 旨在为WEB应用提供可扩 ...
- CentOS7.2 初始化
##安装wget,linux默认最小版本不会安装wget yum -y install wget ##安装文件上传下载到服务器的小工具 yum -y install lrzsz ##安装网络工具包 y ...
- Ubuntu16.04安装xampp及部署Testlink
一.从官网下载xampp并安装: https://www.apachefriends.org/zh_cn/index.html chmod +x xampp-linux-x64-5.6.30-0-in ...
- mariadb 长链接时间限制导致队列消费进程崩溃
项目是一个数据同步项目,线下Android客户端把本地sqllite数据提交到云端队列,php做守护进程消费队列,以同步数据.初测没有问题,可是时不时出现诡异的崩溃,因为设置了错误邮件报警,发现错误代 ...