题解 P3835 【【模板】可持久化平衡树】
看了一篇题解区,这题的比较主流的几种解法分别是
为什么
考虑
同样,在删除的时候,只要不
因此考虑将
只要碰到
int maintain(int o){
int nw=nnd(t[o].v,t[o].w,t[o].ls,t[o].rs);
if(t[t[nw].ls].w>t[t[nw].rs].w*ratio){
t[nw].ls=maintain(t[nw].ls);
t[nw].rs=maintain(t[nw].rs);
t[nw].rs=merge(t[t[nw].ls].rs,t[nw].rs);
t[nw].ls=t[t[nw].ls].ls;
}
if(t[t[nw].rs].w>t[t[nw].ls].w*ratio){
t[nw].ls=maintain(t[nw].ls);
t[nw].rs=maintain(t[nw].rs);
t[nw].ls=merge(t[nw].ls,t[t[nw].rs].ls);
t[nw].rs=t[t[nw].rs].rs;
}
return nw;
}
由于在实际操作的时候一共只加了一个节点,并不会对很多节点的子树大小关系产生影响。
可以证明,每次修改最多只需对
顾在修改时时间复杂度为
#include <bits/stdc++.h>
using namespace std;
inline int read(){
register int x=0;
register bool f=0;
register char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<3)+(x<<1)+c-48;
c=getchar();
}
return f?-x:x;
}
char cr[200];int tt;
inline void print(int x,char k='\n') {
if(!x) putchar('0');
if(x < 0) putchar('-'),x=-x;
while(x) cr[++tt]=x%10+'0',x/=10;
while(tt) putchar(cr[tt--]);
putchar(k);
}
const int maxn=500010;
const int ratio=4;
struct lef{
int v,w,ls,rs;
}t[maxn*200];
int rt[maxn],tot;
int nnd(int v,int w,int ls,int rs){
t[++tot]=(lef){v,w,ls,rs};
return tot;
}
int merge(int x,int y){
return nnd(t[y].v,t[x].w+t[y].w,x,y);
}
void pushup(int o){
if(!t[t[o].ls].w){
return;
}
t[o].w=t[t[o].ls].w+t[t[o].rs].w;
t[o].v=t[t[o].rs].v;
}
int maintain(int o){
int nw=nnd(t[o].v,t[o].w,t[o].ls,t[o].rs);
if(t[t[nw].ls].w>t[t[nw].rs].w*ratio){
t[nw].ls=maintain(t[nw].ls);
t[nw].rs=maintain(t[nw].rs);
t[nw].rs=merge(t[t[nw].ls].rs,t[nw].rs);
t[nw].ls=t[t[nw].ls].ls;
}
if(t[t[nw].rs].w>t[t[nw].ls].w*ratio){
t[nw].ls=maintain(t[nw].ls);
t[nw].rs=maintain(t[nw].rs);
t[nw].ls=merge(t[nw].ls,t[t[nw].rs].ls);
t[nw].rs=t[t[nw].rs].rs;
}
return nw;
}
int find(int o,int k) {
if(t[o].w==1) return 1;
if(k<=t[t[o].ls].v)return find(t[o].ls,k);
else return t[t[o].ls].w+find(t[o].rs,k);
}
int select(int o,int k) {
if(t[o].w==1) return t[o].v;
if(k<=t[t[o].ls].w)return select(t[o].ls,k);
else return select(t[o].rs,k-t[t[o].ls].w);
}
int insert(int o,int x){
int nw=nnd(t[o].v,t[o].w,t[o].ls,t[o].rs);
if(t[nw].w==1){
t[nw].ls=nnd(min(t[nw].v,x),1,0,0);
t[nw].rs=nnd(max(t[nw].v,x),1,0,0);
}
else if(x>t[t[nw].ls].v)
t[nw].rs=insert(t[nw].rs,x);
else
t[nw].ls=insert(t[nw].ls,x);
pushup(nw);
return nw;
}
int erase(int o,int x){
int nw=nnd(t[o].v,t[o].w,t[o].ls,t[o].rs);
if(t[nw].w==1&&t[nw].v!=x)
return nw;
else if(t[t[nw].ls].w==1&&t[t[nw].ls].v==x)
nw=t[nw].rs;
else if(t[t[nw].rs].w==1&&t[t[nw].rs].v==x)
nw=t[nw].ls;
else if(x>t[t[nw].ls].v)
t[nw].rs=erase(t[nw].rs,x);
else
t[nw].ls=erase(t[nw].ls,x);
pushup(nw);
return nw;
}
signed main(){
int n=read();
rt[0]=nnd(2147483647,1,0,0);
for(int i=1;i<=n;i++){
int wh=read(),opt=read(),x=read();
if(opt==1){
rt[i]=maintain(insert(rt[wh],x));
}
if(opt==2){
rt[i]=maintain(erase(rt[wh],x));
}
if(opt==3){
print(find(rt[wh],x));
rt[i]=rt[wh];
}
if(opt==4){
print(select(rt[wh],x));
rt[i]=rt[wh];
}
if(opt==5){
int rk=find(rt[wh],x);
if(rk==1)print(-2147483647);
else print(select(rt[wh],rk-1));
rt[i]=rt[wh];
}
if(opt==6){
int rk=find(rt[wh],x+1);
print(select(rt[wh],rk));
rt[i]=rt[wh];
}
}
return 0;
}