BOZJ2733 [HNOI2012]永无乡(Treap+启发式合并)

【题解】

Treap 启发式合并:


初始时给每个点建一个treap,连边时启发式合并,将小的treap的每个结点插入大的treap中,并delete掉多余结点 


【代码】

#include<stdio.h>
#include<stdlib.h>
int fa[100005],num[100005];
struct Node
{
	Node* ch[2];
	int v,r,s;
	int cmp_v(int x) const
	{
		if(x==v) return -1;
		if(x<v) return 0;
		return 1;
	}
	int cmp_s(int x) const
	{
		if( x == ch[0]->s + 1 ) return -1;
		if( x <= ch[0]->s ) return 0;
		return 1;
	}
};
Node *root[100005],*null;
int father(int x)
{
	if(fa[x]!=x) fa[x]=father(fa[x]);
	return fa[x];
}
void init(int n)
{
	int i;
	null=new Node();
	null->ch[0]=null->ch[1]=NULL;
	null->v=null->s=null->r=0;
	for(i=0;i<=n;i++)
	{
		root[i]=null;
		fa[i]=i;
	}
}
void wh(Node* &o)
{
	o->s = o->ch[0]->s + o->ch[1]->s + 1;
}
void xz(Node* &o,int d)
{
	Node* k=o->ch[d^1];
	o->ch[d^1]=k->ch[d];
	k->ch[d]=o;
	wh(o);
	wh(k);
	o=k;
}
void tj(Node* &o,int x)
{
	int d=o->cmp_v(x);
	if(o==null)
	{
		o=new Node();
		o->ch[0]=o->ch[1]=null;
		o->v=x;
		o->r=rand();
		o->s=1;
		return;
	}
	o->s++;
	tj(o->ch[d],x);
	if( o->ch[d]->r < o->r ) xz(o,d^1);
}
void cr(Node* &x,Node* &y)//将x树插入y树 
{
	if(x->ch[0]!=null) cr(x->ch[0],y);
	if(x->ch[1]!=null) cr(x->ch[1],y);
	tj(y,x->v);
	delete x;//释放空间 
	x=null;
}
void hb(int x,int y)//合并以root[x]为根的树和以root[y]为根的树,启发式合并 
{
	if( root[x]->s < root[y]->s )
	{
		fa[x]=y;
		cr(root[x],root[y]);
	}
	else
	{
		fa[y]=x;
		cr(root[y],root[x]);
	}
}
int cx(Node* &o,int k)
{
	int d=o->cmp_s(k);
	if(d==-1) return o->v;
	if(d==1) k -= o->ch[0]->s + 1;
	return cx(o->ch[d],k);
}
int main()
{
	srand(25);
	char s[5];
	int n,m,q,i,x,y;
	scanf("%d%d",&n,&m);
	init(n);
	for(i=1;i<=n;i++)
	{
		scanf("%d",&x);
		num[x]=i; 
		tj(root[i],x);
	}
	for(i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		if(father(x)!=father(y)) hb(fa[x],fa[y]);
	}
	scanf("%d",&q);
	for(;q>0;q--)
	{
		scanf("%s%d%d",s,&x,&y);
		if(s[0]=='B')
			if(father(x)!=father(y)) hb(fa[x],fa[y]);
		if(s[0]=='Q')
		{
			if( root[father(x)]->s < y ) printf("-1\n");
			else printf("%d\n",num[cx(root[fa[x]],y)]);
		}
	}
	return 0; 
}


你可能感兴趣的:(treap,启发式合并)