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 国的必修技能.有一天 ...
随机推荐
- css兼容问题 ie6,7
H5标签兼容 元素浮动之后能设置宽度的话就给元素加宽度,如果需要元素宽度是内容撑开,就给他里面的块元素加上浮动 第一块加浮动,第二块加margin等于第一块元素在IE6下会有间隙问题 IE6下子元素超 ...
- 介绍CPU,内存,硬盘,指令以及他们之间的关系
CPU:CPU,又称CPU芯片,中央处理器.是计算机上最重要的集成电路,位于计算机的主板上面,其主要任务是从主存上面提取指令和对指令进行执行,CPU包括运算逻辑部件.寄存器部件,运算器和控制部件等.C ...
- Hibernate之关联映射(一对多和多对一映射,多对多映射)
~~~接着之前的Hibernate框架接着学习(上篇面试过后发现真的需要学习以下框架了,不然又被忽悠让去培训.)~~~ 1:Hibernate的关联映射,存在一对多和多对一映射,多对多映射: 1.1: ...
- 【好记性不如烂笔头】死锁之java代码
死锁: 是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称 ...
- CSS与HTML5响应式图片
随着 Retina 屏幕的逐渐普及,网页中对图片的适配要求也越来越高.如何让图片在放大了两倍的 Retina 屏幕显示依然清晰,曾经一度困扰着网页开发者,好在 CSS3 与 HTML5 已经着力在改变 ...
- pyqt样式表语法笔记(上) --原创
pyqt样式表语法笔记(上) pyqt QSS python 样式表 因为软件课设的原因开始学习使用pyqt4,才发现原来它也有样式表,而且语法跟css基本相同,而且一些功能实现起来感觉比js要简单方 ...
- 用代码控制退出APP
+ (void)exitApplication { AppDelegate *app = [UIApplication sharedApplication].delegate; UIWindow *w ...
- 现代3D图形编程学习-你好,三角形(译)
你好,三角形 传统的入门教程在介绍编程语言的时候,通常从"Hello,World!"的程序开始.这样的程序拥有最简单的能够直接输出"Hello, World!" ...
- CF #404 (Div. 2) D. Anton and School - 2 (数论+范德蒙恒等式)
题意:给你一个由'('和')'组成的字符串,问你有多少个子串,前半部分是由'('组成后半部分由')'组成 思路:枚举这个字符串中的所有'('左括号,它左边的所有'('左括号的个数为num1,它的右边的 ...
- 文件系统与linux相关知识点
文件系统是操作系统中管理持久性数据的子系统,提供数据存储和访问功能.对于服务器开发人员,比较关注的是unix(linux)环境下的文件系统,比如分区与磁盘关系,磁盘的剩余空间,文件的类型与权限控制,文 ...