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 国的必修技能.有一天 ...
随机推荐
- JAVA基础知识(2)--堆栈和递归的操作
2015-07-26 18:16:21/***该应用程序对堆栈和递归方法进行实例操作: *1.堆栈操作:先进后出,*2.递归方法:直接或者调用自己的方法:*@author lhm *Email:912 ...
- 通过hue提交oozie定时任务
Oozie是什么? Oozie是一种Java Web应用程序,它运行在Java servlet容器——即Tomcat——中,并使用数据库来存储以下内容: 工作流定义 当前运行的工作流实例,包括实例的状 ...
- 使用Java语言开发微信公众平台(四)——图文消息的发送与响应
在上一篇文章中,我们实现了被关注回复与关键词回复功能.在用户关注的时候自动推送功能菜单,并根据用户输入的关键词,回复特定信息.但是,我们只能回复文本消息给用户,如何才回复一条图文消息呢?本周,我们一起 ...
- 零件库管理信息系统设计--part03:管理员登录部分设计
兄弟们,我又回来啦! 上次我把表建完了.今天来点干货,我们用ssm框架来先简单实现一下管理员的登录功能. 在实现之前,我对user表(管理员表)做了些简单的修改,先来看看: 忽略哪些蓝色的马赛克和乱输 ...
- salesforce 零基础学习(六十七)SingleEmailMessage 那点事
在salesforce开发中,发送邮件是一个很常见的功能.比如在进入审批流以后的通过和拒绝的操作需要发送邮件给记录的owner,和其他系统交互以后更改了某些状态通知相关的User或者Contact等等 ...
- flex中为控件添加监听器并计算
1.添加监听器: public function moduleCreationComplete():void { this.D601_29a.addEventListener(FlexEvent.SE ...
- css3特效
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title> ...
- ios微信自动播放音乐
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8 ...
- 区分 点操作符+属性名 和 getAttribute()
在用DOM操作控制HTML时,很多初学者会把 点操作符+属性名 与getAttribute("属性名") 混淆,误以为这两种方法是等价的. 实际上, 通过getAttribute( ...
- 关于RestfulAPI与SpringMVC之间的传值
##默认读者已经搭建好的SpringMVC的环境,并且对SpringMVC有着一定的了解,并且已经对RestfulAPI有了一定的了解 1,首先将WEB-INF下的web.xml里面的url-part ...