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 国的必修技能.有一天 ...
随机推荐
- Static语句块和初始语句块的使用---2015年10月恒生电子笔试试卷
package lhm.test; /** * @author lenovo * */public class Person { private int id; private static int ...
- Linux云自动化运维第三课
Linux云自动化运维第三课 一.正则表达式 1.匹配符 * ###匹配0到任意字符 ? ###匹配单个字符 [[:alpha:]] ###匹配单个字母 [[:lower:]] ###匹配单个小写字母 ...
- python自学基础1week
一.python老师介绍 二.为什么要学习python? 三.学习python有前途吗? 疗程1:语言基础 疗程2:网络编程 疗程3:web基础开发 疗程4:算法&设计模式 疗程5:pytho ...
- ECMA script 6的新特性
简单介绍下ES6的新特性: (1)箭头操作符 :简化了函数的书写 (2)类的支持:引入了class关键字,对象的创建,继承更加直观,父类方法的调用,实例化,构造函数等概念更加形象化. (3)增强的对象 ...
- 使用Struts2校验器
今天遇到了这样的问题:我的jsp页面.web.xml.struts.xml.UserAction-validation.xml等内容写的都正确,就是无法使用校验器!在网上找了半天就是不出来,迫不得已我 ...
- Grunt usemin
yeoman/grunt-usemin 用来将 HTML 文件中(或者 templates/views)中没有优化的 script 和 stylesheets 替换为优化过的版本. usemin 暴露 ...
- 百度api的使用
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- 任务调度之持久化(基于Quartz.net)
上一篇我们了解了任务调度及他的远端管理方式,传送门:任务调度及远端管理(基于Quartz.net) 这篇我们要完成任务调度的持久化功能,即新增修改删除之类的功能,这必须得要有的,不然都不知道后台都有什 ...
- python 调取 shell 命令的几种方法
os.system()无法获得到输出和返回值 os.popen()output = os.popen('cat /proc/cpuinfo')print output.read()返回的是 file ...
- 浩哥解析MyBatis源码(四)——DataSource数据源模块
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6634880.html 1.回顾 上一文中解读了MyBatis中的事务模块,其实事务操作无非 ...