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; 
}


發佈了110 篇原創文章 · 獲贊 8 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章