Treap44分求助
查看原帖
Treap44分求助
386385
ChenErxiang楼主2023/8/4 13:19
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline ll read()
{
    ll s=0,w=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
    return s*w;
}
ll Max(ll A,ll B){return A>B?A:B;}
ll Min(ll A,ll B){return A<B?A:B;}


const ll maxn=1e5+10,INF=1e9;
ll fa[maxn],son[maxn][2],tot;//Treap
// son[x][0]:左二子 son[x][1]:右儿子
ll v[maxn],key[maxn];//权值、 优先级
ll size[maxn],sum[maxn];//该子树(节点)的大小、该子树(节点)的和 
ll root;//根节点的编号
ll cnt[maxn];//防止有权值相同的节点 

void update(ll x)
{
	sum[x]=sum[son[x][0]]+sum[son[x][1]]+v[x]*cnt[x];
	size[x]=size[son[x][0]]+size[son[x][1]]+cnt[x];
}

void rotate(ll x)//节点x上旋 
{
    ll y=fa[x],z=fa[y],d=(son[y][1]==x);
    if(z)son[z][son[z][1]==y]=x;//y非根节点(根节点的父亲为节点0) 
//  son[x][!d]->son[y][d];
    fa[x]=z;fa[y]=x;fa[son[x][!d]]=y;
    son[y][d]=son[x][!d];son[x][!d]=y;
    update(y);update(x);if(y==root)root=x;
}

void print(ll x) {
	if (!x) return;
	print(son[x][0]);
	printf("%lld %lld\n", v[x], cnt[x]);
	print(son[x][1]);
}
void insert(ll &x,ll f,ll k)//在x的子树里插入权值为k的点,f:点x的父亲 
{
    if(!x)//访问到空节点 
    {
        x=++tot;fa[x]=f;cnt[x]=1;
        v[x]=sum[x]=k;key[x]=rand();
        size[x]=1;son[x][0]=son[x][1]=0;
        return ;
    }
    if(k==v[x])
	{
		cnt[x]++;return ;
	}
	ll d=k<v[x]?0:1;
	insert(son[x][d],x,k);
	if(key[son[x][d]]<key[x])rotate(son[x][d]);//保证优先级满足堆的性质
    update(x);
}

void earse(ll x)//删除节点x
{
	if(!x)return ;
    if(cnt[x]>1){cnt[x]--;size[x]--;update(x);return ;}
    if(son[x][0]&&son[x][1])
    {
        if(key[son[x][0]]<key[son[x][1]])rotate(son[x][0]);
        else rotate(son[x][1]);
    }
    else
    {
        ll v=son[x][0]+son[x][1],d=(son[fa[x]][1]==x);
        if(fa[x])son[fa[x]][d]=v;if(v)fa[v]=fa[x];
        if(fa[x])update(fa[x]);
        ll tmp=fa[x];
        fa[x]=0;
        son[x][0]=son[x][1]=0;
        size[x]=0;cnt[x]=0;
        if(x==root)root=v;
        while(tmp){update(tmp);tmp=fa[tmp];}
	}
}

ll find(ll p,ll x)//找到值为x的节点的编号 
{
	if(!p)return 0;
	if(v[p]==x)return p;
	else
	{
		ll d=x<v[p]?0:1;
		return find(son[p][d],x);
	}
}

ll find_p(ll p,ll x)//找到值为x的数是第几个 
{
	if(!p)return 0;
	if(v[p]==x)return size[son[p][0]]+1;
	else 
	{
		if(x<v[p])return find_p(son[p][0],x);
		else return size[son[p][0]]+cnt[p]+find_p(son[p][1],x);
	}
}

ll find_v(ll p,ll x)//找到第x个数的值 
{
	if(!p)return INF;
	if(x>size[son[p][0]]&&x<=size[son[p][0]]+cnt[p])return v[p];
	else
	{
		if(x<=size[son[p][0]])return find_v(son[p][0],x);
		else return find_v(son[p][1],x-size[son[p][0]]-cnt[p]);
	}
}

ll find_pre(ll p,ll x)//求小于x的最大值 
{
	if(!p)return -INF;
	if(v[p]<x)return Max(find_pre(son[p][1],x),v[p]);
	else return find_pre(son[p][0],x);
} 

ll find_nex(ll p,ll x)//求大于x的最小值 
{
	if(!p)return INF;
	if(v[p]>x)return Min(find_nex(son[p][0],x),v[p]);
	else return find_nex(son[p][1],x);
}

ll find_sum(ll p,ll x,ll y)//求第x小到第y小的和
{
	
}

int main()
{
    ll n,opt,x;
	root=0;
	n=read();
	for(ll i=1;i<=n;i++)
	{
//		print(root); 
		opt=read();
		x=read();
		switch(opt)
		{
			case 1:insert(root,fa[root],x);break;
			case 2:earse(find(root,x));break;
			case 3:printf("%lld\n",find_p(root,x));break;
			case 4:printf("%lld\n",find_v(root,x));break;
			case 5:printf("%lld\n",find_pre(root,x));break;
			case 6:printf("%lld\n",find_nex(root,x));break;
			case 7:ll y=read();printf("%lld\n",find_sum(root,x,y));break;
		}
	}
} 
2023/8/4 13:19
加载中...