题目大意
求用
spaly
维护
m
个操作,每次操作的节点的深度。
操作分为
数据范围
1≤m≤105,1≤key≤109
.
保证出现的每个
key
值都不和前面存在的重复,保证操作合法。
解题报告
以单旋最小值为例说明单旋的一些性质:
最小值
x
在
此时,整棵树深度的变化如下,
单旋最大值的情况与此类似,
注意到,这棵树的
剩下的问题就只是如何维护插入的操作。
若插入时树不为空,则插入后,新节点
x
要么是它在树中前驱
若两者不同时存在,那么问题就好办了;
对于两者同时存在的情况, prev 和 next 一定存在祖先关系(否则设 y=lca(prev,next) ,则 prev<y<next ,与前驱和后继的定义矛盾)
比较 prev 和 next 的深度判断谁是祖先,若 prev 是祖先,则 prev 存在右儿子, next 不存在左儿子(一样是反证法可证);若 next 是祖先,则 next 存在左儿子, prev 不存在右儿子。
因此,可以使用两个树状数组,第一个用来求前驱后继和最大最小值,第二个用来维护深度的增量,就可以解决这道题了。
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int gint(){
char c; int f=1;
while(c=getchar(),c<48||c>57)
if(c=='-')f=-1;
int x=0;
for(;c>47&&c<58;c=getchar()){
x=x*10+c-48;
}
return x*f;
}
#define max_N 100005
int n,m,a[max_N],b[max_N],h[max_N];
int bit1[max_N],bit2[max_N];
inline void add(int*bit,int x,int y){
for(int i=x;i&&i<=n;i+=i&-i)bit[i]+=y;
}
inline int sum(int*bit,int x){
int res=0;
for(int i=x;i;i-=i&-i)res+=bit[i];
return res;
}
inline int k_th(int k){
int ans=0;
for(int i=17;~i;--i){
ans^=1<<i;
if(ans>=n||bit1[ans]>=k)ans^=1<<i;
else k-=bit1[ans];
}
return ans+1;
}
inline int hash(int x){
return lower_bound(h+1,h+1+n,x)-h;
}
int rt,sz,p[max_N],ch[2][max_N],dep[max_N];
int main(){
m=gint();
for(int i=1;i<=m;++i){
a[i]=gint();
if(a[i]==1)h[++n]=b[i]=gint();
}
sort(h+1,h+1+n);
for(int i=1;i<=m;++i){
if(a[i]==1){
int x=hash(b[i]);
if(!rt)rt=x;
else{
int rk,pre=0,nex=0;
rk=sum(bit1,x)+1;
if(rk<=sz)nex=k_th(rk);
rk=sum(bit1,x-1);
if(rk)pre=k_th(rk);
if(!pre||dep[pre]+sum(bit2,pre)<dep[nex]+sum(bit2,nex)){
p[x]=nex;
ch[0][nex]=x;
}
else{
p[x]=pre;
ch[1][pre]=x;
}
}
dep[x]=sum(bit2,p[x])+dep[p[x]]+1;
int tmp=sum(bit2,x);
add(bit2,x,-tmp),add(bit2,x+1,tmp);
add(bit1,x,1),++sz;
printf("%d\n",dep[x]);
}
else if(a[i]==2||a[i]==4){
int x=k_th(1),tmp=sum(bit2,x);
printf("%d\n",dep[x]+tmp);
if(x!=rt){
dep[x]=1-tmp;
add(bit2,p[x],1);
if(ch[1][x])ch[0][p[x]]=ch[1][x],p[ch[1][x]]=p[x];
ch[1][x]=rt,p[rt]=x;
p[x]=0,rt=x;
}
if(a[i]==4){
add(bit1,x,-1),--sz;
rt=ch[1][x],p[rt]=0;
add(bit2,1,-1);
}
}
else{
int x=k_th(sz),tmp=sum(bit2,x);
printf("%d\n",dep[x]+tmp);
if(x!=rt){
dep[x]=1-tmp;
add(bit2,1,1),add(bit2,p[x]+1,-1);
if(ch[0][x])ch[1][p[x]]=ch[0][x],p[ch[0][x]]=p[x];
ch[0][x]=rt,p[rt]=x;
p[x]=0,rt=x;
}
if(a[i]==5){
add(bit1,x,-1),--sz;
rt=ch[0][x],p[rt]=0;
add(bit2,1,-1);
}
}
}
return 0;
}