模板—Splay

#include<iostream>
#include<cstring>
#include<cstdio>
#define LL long long
using namespace std;
struct Splay
{
    struct node
    {
        int ch[2],fa,val,cnt,siz;
        #define l(x) tr[x].ch[0] 
        #define r(x) tr[x].ch[1]
        #define fa(x) tr[x].fa
        #define val(x) tr[x].val
        #define cnt(x) tr[x].cnt
        #define siz(x) tr[x].siz
    }tr[1000010];
    int sz,root;
    void clear(int x){fa(x)=l(x)=r(x)=val(x)=cnt(x)=siz(x)=0;}
    bool get(int x){return r(fa(x))==x;}
    int newnode(int x)
    {    
        sz++;val(sz)=x;cnt(sz)=siz(sz)=1;
        fa(sz)=l(sz)=r(sz)=0;return sz;
    }
    void pushup(int x)
    {
        if(!x)return;
        siz(x)=cnt(x);
        if(l(x))siz(x)+=siz(l(x));
        if(r(x))siz(x)+=siz(r(x));
    }
    void rotate(int x)
    {
        int old=fa(x),oldf=fa(old),which=get(x);
        tr[old].ch[which]=tr[x].ch[which^1];fa(tr[old].ch[which])=old;
        tr[x].ch[which^1]=old;fa(old)=x;fa(x)=oldf;
        if(oldf)tr[oldf].ch[tr[oldf].ch[1]==old]=x;
        pushup(old);pushup(x);
    }
    void splay(int x)
    {
        for(int f;f=fa(x);rotate(x))
        if(fa(f))rotate((get(x)==get(f))?f:x);
        root=x;
    }
    void insert(int x)
    {    
        if(!root){root=newnode(x);return;}
        int now=root,fa=0;
        while(1)
        {
            if(x==val(now)){cnt(now)++,pushup(now),pushup(fa);splay(now);return;}
            fa=now,now=tr[now].ch[val(now)<x];
            if(!now)
            {
                int tem=newnode(x);
                tr[fa].ch[x>val(fa)]=tem;
                fa(tem)=fa;val(tem)=x;
                pushup(fa);splay(tem);return;
            }
        }
    }
    int rnk(int x)
    {
        int now=root,ans=0;
        while(1)
        {
            if(x<val(now))now=l(now);
            else
            {
                ans+=siz(l(now));
                if(x==val(now)){splay(now);return ans+1;}
                ans+=cnt(now);now=r(now);
            }
        }
    }
    int kth(int x)
    {
        int now=root;
        while(1)
        {
            if(l(now)&&x<=siz(l(now)))now=l(now);
            else
            {
                int tem=siz(l(now))+cnt(now);
                if(x<=tem)return val(now);
                x-=tem;now=r(now);
            }
        }
    }
    int pre(){int now=l(root);while(r(now))now=r(now);return now;}
    int nxt(){int now=r(root);while(l(now))now=l(now);return now;}
    void del(int x)
    {
        rnk(x);
        if(cnt(root)>1){cnt(root)--;pushup(root);return;}
        if(!l(root)&&!r(root)){clear(root);root=0;return;}
        if(!l(root)){int rt=root;root=r(rt);fa(root)=0;clear(rt);return;}
        if(!r(root)){int rt=root;root=l(rt);fa(root)=0;clear(rt);return;}
        int oldrt=root,leftbig=pre();
        splay(leftbig);r(root)=r(oldrt);
        fa(r(oldrt))=root;clear(oldrt);pushup(root);
    }
}T;
signed main()
{
    int n;cin>>n;int opt,x;
    for(int i=1;i<=n;i++)
    {    
        cin>>opt>>x;
        if(opt==1)T.insert(x);
        if(opt==2)T.del(x);
        if(opt==3)cout<<T.rnk(x)<<endl;
        if(opt==4)cout<<T.kth(x)<<endl;
        if(opt==5){T.insert(x);cout<<T.val(T.pre())<<endl;T.del(x);}
        if(opt==6){T.insert(x);cout<<T.val(T.nxt())<<endl;T.del(x);}
    }
}
View Code

一个封装比较好的splay板子,不过不知道为啥常数稍大。

UPD:又打了一个,还好点

#include<iostream>
#include<cstring>
#include<cstdio>
#define LL long long
using namespace std;
struct Splay
{
	#define N 300010
	int ch[N][2],fa[N],siz[N],key[N],cnt[N];
	int sz,rt;
	void clear(int x){ch[x][0]=ch[x][1]=fa[x]=siz[x]=key[x]=cnt[x]=0;}
	int get(int x){return ch[fa[x]][1]==x;}
	void pushup(int x)
	{
		if(!x)return;siz[x]=cnt[x];
		if(ch[x][0])siz[x]+=siz[ch[x][0]];
		if(ch[x][1])siz[x]+=siz[ch[x][1]];
	}
	void rotate(int x)
	{
		int wh=get(x),f=fa[x],of=fa[f];
		ch[f][wh]=ch[x][wh^1];fa[ch[f][wh]]=f;
		ch[x][wh^1]=f;fa[f]=x;fa[x]=of;
		if(of)ch[of][ch[of][1]==f]=x;
		pushup(f);pushup(x);
	}
	void splay(int x)
	{
		for(int f;f=fa[x];rotate(x))
		if(fa[f])rotate((get(x)==get(f))?f:x);
		rt=x;
	}
	int node(int x){++sz,siz[sz]=cnt[sz]=1;key[sz]=x;fa[sz]=ch[sz][0]=ch[sz][1]=0;return sz;}
	void insert(int x)
	{	
		if(!rt){rt=node(x);return;}
		int now=rt,f=0;
		while(1)
		{
			if(key[now]==x){cnt[now]++,pushup(now),pushup(f);splay(now);return;}
			f=now;now=ch[now][x>key[now]];
			if(!now)
			{	
				int tem=node(x);ch[f][x>key[f]]=tem;
				fa[tem]=f;pushup(f);pushup(tem);splay(tem);return;
			}
		}
	}
	int kth(int k)
	{
		int p=rt;
		while(1)
		{
			if(ch[p][0]&&siz[ch[p][0]]>=k)p=ch[p][0];
			else if(siz[ch[p][0]]+cnt[p]>=k)return key[p];
			else k-=siz[ch[p][0]]+cnt[p],p=ch[p][1];
		}
	}
	int rnk(int x)
	{
		int p=rt,al=0;
		while(1)
		{	
			if(x<key[p])p=ch[p][0];
			else 
			{
				al+=siz[ch[p][0]];
				if(x==key[p]){splay(p);return al+1;}
				al+=cnt[p];p=ch[p][1];
			}
		}
	}
	int pre(){int now=ch[rt][0];while(ch[now][1])now=ch[now][1];return now;}
	int nxt(){int now=ch[rt][1];while(ch[now][0])now=ch[now][0];return now;}
	void del(int x)
	{	
		rnk(x);
		if(cnt[rt]>1){cnt[rt]--;pushup(rt);return;}
		if(!ch[rt][0]&&!ch[rt][1]){clear(rt);rt=0;return;}
		if(!ch[rt][0]){int root=rt;rt=ch[rt][1];fa[rt]=0;clear(root);return;}
		if(!ch[rt][1]){int root=rt;rt=ch[rt][0];fa[rt]=0;clear(root);return;}
		int oldrt=rt,leftbig=pre();
		splay(leftbig);ch[rt][1]=ch[oldrt][1];
		fa[ch[oldrt][1]]=rt;clear(oldrt);pushup(rt);
	}
}T;
signed main()
{
	int n;cin>>n;int opt,x;
	for(int i=1;i<=n;i++)
	{	
		cin>>opt>>x;
		if(opt==1)T.insert(x);
		if(opt==2)T.del(x);
		if(opt==3)cout<<T.rnk(x)<<endl;
		if(opt==4)cout<<T.kth(x)<<endl;
		if(opt==5){T.insert(x);cout<<T.key[T.pre()]<<endl;T.del(x);}
		if(opt==6){T.insert(x);cout<<T.key[T.nxt()]<<endl;T.del(x);}
	}
}
原文地址:https://www.cnblogs.com/Al-Ca/p/11576179.html