• 【题解】可持久化平衡树


    Problem

    ( ext{Solution:})

    考虑用 fhq_treap 来实现这个东西。

    每次的新建版本,我们可以新建一个根,并直接利用 merge 和 split 操作在上一个版本上利用信息。

    注意 split 和 merge 中都需要新建节点,否则会影响之前版本的结构。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int MAXN=5e5+10;
    const int INF=1000000001;
    const int N=MAXN<<6;
    int rt[MAXN],tr[N][2];
    int siz[N],cv[N],val[N];
    int cnt;
    inline int read() {
    	int s=0,w=1;
    	char ch=getchar();
    	while(!isdigit(ch)) {
    		if(ch=='-')w=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch)) {
    		s=s*10-48+ch;
    		ch=getchar();
    	}
    	return w*s;
    }
    inline int rd(){return rand()<<15|rand();}
    inline int bd(int v){
    	val[++cnt]=v;
    	siz[cnt]=1;
    	cv[cnt]=rd();
    	return cnt;
    }
    inline void pushup(int x){siz[x]=siz[tr[x][0]]+siz[tr[x][1]]+1;}
    void split(int now,int k,int &x,int &y){
    	if(!now){x=y=0;return;}
    	if(val[now]<=k){
    		x=++cnt;
    		tr[x][0]=tr[now][0];
    		tr[x][1]=tr[now][1];
    		val[x]=val[now];
    		siz[x]=siz[now];
    		cv[x]=cv[now];
    		split(tr[x][1],k,tr[x][1],y);
    		pushup(x);
    	}
    	else{
    		y=++cnt;
    		tr[y][0]=tr[now][0];
    		tr[y][1]=tr[now][1];
    		val[y]=val[now];
    		siz[y]=siz[now];
    		cv[y]=cv[now];
    		split(tr[y][0],k,x,tr[y][0]);
    		pushup(y);
    	}
    }
    int merge(int x,int y){
    	if(!x||!y)return x+y;
    	if(cv[x]<cv[y]){
    		int p=++cnt;
    		tr[p][0]=tr[x][0];
    		tr[p][1]=tr[x][1];
    		val[p]=val[x];
    		siz[p]=siz[x];
    		cv[p]=cv[x];
    		tr[p][1]=merge(tr[p][1],y);
    		pushup(p);return p;
    	}
    	else{
    		int p=++cnt;
    		tr[p][0]=tr[y][0];
    		tr[p][1]=tr[y][1];
    		siz[p]=siz[y];
    		val[p]=val[y];
    		cv[p]=cv[y];
    		tr[p][0]=merge(x,tr[p][0]);
    		pushup(p);return p;
    	}
    }
    void del(int &root,int v){
    	int xA=0,yA=0,zA=0;
    	split(root,v,xA,zA);
    	split(xA,v-1,xA,yA);
    	yA=merge(tr[yA][0],tr[yA][1]);
    	root=merge(merge(xA,yA),zA);
    }
    void Ins(int &root,int v){
    	int x=0,y=0;
    	split(root,v,x,y);
    	root=merge(merge(x,bd(v)),y);
    }
    int n,opt;
    int kth(int now,int k){
    	if(k<=siz[tr[now][0]])return kth(tr[now][0],k);
    	if(k==siz[tr[now][0]]+1)return now;
    	return kth(tr[now][1],k-siz[tr[now][0]]-1);
    }
    void dfs(int x){
    	if(tr[x][0])dfs(tr[x][0]);
    	printf("%lld ",val[x]);
    	if(tr[x][1])dfs(tr[x][1]);
    }
    signed main(){
    	n=read();
    //	dfs(rt[0]);puts("");
    	for(int i=1;i<=n;++i){
    		int v=read(),x;
    		opt=read();x=read();
    		rt[i]=rt[v];
    		if(opt==1){Ins(rt[i],x);}
    		else if(opt==2){del(rt[i],x);}
    		else if(opt==3){
    			int A=0,B=0;
    			split(rt[i],x-1,A,B);
    			printf("%lld
    ",siz[A]+1);
    			rt[i]=merge(A,B);
    		}
    		else if(opt==4){printf("%lld
    ",val[kth(rt[i],x)]);}
    		else if(opt==5){
    			int A=0,B=0;
    			split(rt[i],x-1,A,B);
    			if(!A){
    				puts("-2147483647");
    				continue;
    			}
    			printf("%lld
    ",val[kth(A,siz[A])]);
    			rt[i]=merge(A,B);
    		}
    		else{
    			int A=0,B=0;
    			split(rt[i],x,A,B);
    			if(!B){
    				puts("2147483647");
    				continue;
    			}
    			printf("%lld
    ",val[kth(B,1)]);
    			rt[i]=merge(A,B);
    		}
    //		dfs(rt[i]);puts("");
    	}
    	return 0;
    }
    

    注意没有前驱后继的处理,不能在一开始就加进去,那样的排名是不对的。

    细节上就是注意新开节点。

  • 相关阅读:
    宏定义define和const的区别
    C++11新特性(1)
    TCP协议
    sql查询 不等于的坑null
    To B市场品牌实战课 用产品故事引爆市场
    Tomcat在windows服务器下,将tomcat控制台日志记录到日志文件中
    极客时间返现小程序,全网最优惠返现最多
    分布式数据库,从功能特性到运行机制,讲透本质
    生财有术知识星球整理
    ff
  • 原文地址:https://www.cnblogs.com/h-lka/p/14965290.html
Copyright © 2020-2023  润新知