BZOJ3224 普通平衡树

浅谈(splay)https://www.cnblogs.com/AKMer/p/9979592.html

浅谈(fhq)_(treap)https://www.cnblogs.com/AKMer/p/9981274.html

题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3224

平衡树模板题。

时间复杂度:(O(nlogn))

空间复杂度:(O(n))

(splay)版代码如下:

#include <cstdio>
using namespace std;

const int maxn=1e5+5;

int n;

int read() {
    int x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}

struct Splay {
    int tot,root;
    int fa[maxn],son[maxn][2];
    int val[maxn],siz[maxn],cnt[maxn];

    int newnode(int v) {
        val[++tot]=v;
        siz[tot]=cnt[tot]=1;
        return tot;
    }

    int find(int v) {
        int u=root;
        while(val[u]!=v) {
            if(val[u]>v) {if(son[u][0])u=son[u][0];else break;}
            if(val[u]<v) {if(son[u][1])u=son[u][1];else break;}
        }
        return u;
    }

    inline int t(int u) {
        return son[fa[u]][1]==u;
    }

    void updata(int p) {
        siz[p]=siz[son[p][0]]+cnt[p]+siz[son[p][1]];
    }

    void rotate(int u) {
        int ret=t(u),f=fa[u],s=son[u][ret^1];
        son[f][ret]=s;if(s)fa[s]=f;son[u][ret^1]=f;
        fa[u]=fa[f];if(fa[f])son[fa[f]][t(f)]=u;
        fa[f]=u;updata(f);updata(u);
    }

    void splay(int u) {
        while(fa[u]) {
            if(fa[fa[u]]) {
                if(t(fa[u])==t(u))rotate(fa[u]);
                else rotate(u);
            }rotate(u);
        }root=u;
    }
    
    void ins(int v) {
        if(!root) {root=newnode(v);return;}
        int u=find(v);
        if(val[u]==v) {siz[u]++;cnt[u]++;splay(u);return;}
        newnode(v);fa[tot]=u;son[u][val[u]<v]=tot;
        splay(tot);
    }

    void del(int x) {
        if(!root)return;
        int u=find(x);splay(u);
        if((val[u]!=x)||(--cnt[u])) {siz[u]--;return;}
        if(!son[u][0]&&!son[u][1]) {root=0;return;}
        if(!son[u][0]) {root=son[u][1];fa[root]=0;return;}
        if(!son[u][1]) {root=son[u][0];fa[root]=0;return;}
        int node=son[u][0];while(son[node][1])node=son[node][1];
        fa[son[u][0]]=0;splay(node);
        son[root][1]=son[u][1];fa[son[u][1]]=root;
        updata(root);
    }

    int get_rk(int v) {
        int u=find(v);splay(u);
        if(val[u]>=v)return siz[son[u][0]]+1;
        return siz[son[u][0]]+cnt[u]+1;
    }

    int get_val(int rk) {
        int u=root;
        while(rk) {
            if(siz[son[u][0]]>=rk)u=son[u][0];
            if(siz[son[u][0]]<rk&&siz[son[u][0]]+cnt[u]>=rk)break;
            if(siz[son[u][0]]+cnt[u]<rk)rk-=siz[son[u][0]]+cnt[u],u=son[u][1];
        }
        return val[u];
    }

    int get_pre(int v) {
        int u=find(v);splay(u);
        if(val[u]<v)return val[u];
        int node=son[u][0];
        while(son[node][1])node=son[node][1];
        return val[node];
    }
    
    int get_suc(int v) {
        int u=find(v);splay(u);
        if(val[u]>v)return val[u];
        int node=son[u][1];
        while(son[node][0])node=son[node][0];
        return val[node];
    }
}T;

int main() {
    n=read();
    for(int i=1;i<=n;i++) {
        int opt=read(),x=read();
        if(opt==1)T.ins(x);
        if(opt==2)T.del(x);
        if(opt==3)printf("%d
",T.get_rk(x));
        if(opt==4)printf("%d
",T.get_val(x));
        if(opt==5)printf("%d
",T.get_pre(x));
        if(opt==6)printf("%d
",T.get_suc(x));
    }
    return 0;
}

(fhq)_(treap)版代码如下:

#include <ctime>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii;

const int maxn=1e5+5;

int n;

int read() {
	int x=0,f=1;char ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
	return x*f;
}

struct fhq_treap {
	int tot,root;
	int fix[maxn],son[maxn][2];
	int val[maxn],siz[maxn],cnt[maxn];

	int newnode(int v) {
		val[++tot]=v,fix[tot]=rand();
		cnt[tot]=siz[tot]=1;return tot;
	}

	void updata(int p) {
		siz[p]=siz[son[p][0]]+cnt[p]+siz[son[p][1]];
	}

	pii split(int u,int rk) {
		if(!rk)return make_pair(0,u);
		if(rk==siz[u])return make_pair(u,0);
		if(siz[son[u][0]]>=rk) {
			pii tmp=split(son[u][0],rk);
			son[u][0]=tmp.second,updata(u);
			return make_pair(tmp.first,u);
		}
		else {
			pii tmp=split(son[u][1],rk-siz[son[u][0]]-cnt[u]);
			son[u][1]=tmp.first,updata(u);
			return make_pair(u,tmp.second);
		}
	}

	int merge(int a,int b) {
		if(!a||!b)return a+b;
		if(fix[a]>fix[b])return son[a][1]=merge(son[a][1],b),updata(a),a;
		return son[b][0]=merge(a,son[b][0]),updata(b),b;
	}

	int getkth(int u,int v,bool &bo,int delta) {
		if(!u)return 0;int ans=0;
		if(val[u]>v)ans=getkth(son[u][0],v,bo,delta);
		else if(val[u]==v) {
			if(delta!=-1||cnt[u]!=1)cnt[u]+=delta,siz[u]+=delta,bo=1;
			return siz[son[u][0]];
		}
		else ans=siz[son[u][0]]+cnt[u]+getkth(son[u][1],v,bo,delta);
		if(bo)siz[u]+=delta;return ans;
	}
	
	void ins(int v) {
		bool bo=0;int rk=getkth(root,v,bo,1);
		if(bo)return;pii tmp=split(root,rk);
		root=merge(tmp.first,merge(newnode(v),tmp.second));
	}

	void del(int v) {
		bool bo=0;int rk=getkth(root,v,bo,-1)+1;
		if(bo)return;pii tmp1=split(root,rk);
		pii tmp2=split(tmp1.first,rk-1);
		root=merge(tmp2.first,tmp1.second);
	}

	int get_rk(int v) {
		bool bo=0;
		return getkth(root,v,bo,0)+1;
	}

	int get_val(int rk) {
		int u=root;
		while(rk) {
			if(siz[son[u][0]]>=rk)u=son[u][0];
			if(siz[son[u][0]]<rk&&siz[son[u][0]]+cnt[u]>=rk)break;
			if(siz[son[u][0]]+cnt[u]<rk)rk-=siz[son[u][0]]+cnt[u],u=son[u][1];
		}
		return val[u];
	}

	int get_pre(int v) {
		int rk=get_rk(v)-1;
		return get_val(rk);
	}

	int get_suc(int v) {
		int rk=get_rk(v+1);
		return get_val(rk);
	}
}T;

int main() {
	srand(time(0));n=read();
	for(int i=1;i<=n;i++) {
		int opt=read(),x=read();
		if(opt==1)T.ins(x);
		if(opt==2)T.del(x);
		if(opt==3)printf("%d
",T.get_rk(x));
		if(opt==4)printf("%d
",T.get_val(x));
		if(opt==5)printf("%d
",T.get_pre(x));
		if(opt==6)printf("%d
",T.get_suc(x));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/AKMer/p/9985277.html