【BZOJ 2733】 [HNOI2012]永无乡|Splay启发式合并

代码能力太弱

#include <cstdio>
#include <iostream>
#include <algorithm> 
using namespace std;
#define MAXN 100010
int father[MAXN],root[MAXN];
int fa[MAXN],to[MAXN][2],size[MAXN],num[MAXN],id[MAXN];
int n,m;
int laji[MAXN],top;
void Up(int x){ size[x]=size[to[x][0]]+size[to[x][1]]+1; }
void Rotate(int &rt,int x)
{
	int y=fa[x],z=fa[y];
	if(y==rt) rt=x;
	else to[z][to[z][1]==y]=x;
	int c=to[y][1]==x;
	fa[x]=z;fa[y]=x;fa[to[x][c^1]]=y;
	to[y][c]=to[x][c^1];to[x][c^1]=y;
	Up(y);Up(x); 
}
void Splay(int &rt,int x)
{
	while(rt!=x)
	{
		if(fa[x]!=rt) Rotate(rt,fa[x]);
		Rotate(rt,x);
	}
}
void Ins(int &now,int &rt,int ID,int NUM,int last)
{
	if(now==0){now=laji[top--];num[now]=NUM;id[now]=ID;fa[now]=last;size[now]=1;Splay(rt,now);return ;}
	if(NUM<=num[now]) Ins(to[now][0],rt,ID,NUM,now);
	else Ins(to[now][1],rt,ID,NUM,now);
}
void Dfs(int &rt,int now)
{
	if(now==0) return ;
	Dfs(rt,to[now][0]);
	Dfs(rt,to[now][1]);
	Ins(rt,rt,id[now],num[now],0);
	fa[now]=to[now][0]=to[now][1]=size[now]=id[now]=num[now]=0;
	laji[++top]=now;
}
int F(int x)
{
	if(father[x]!=x) father[x]=F(father[x]);
	return father[x];
}
void Link(int x,int y)
{
	x=F(x);y=F(y);
	if(x==y) return ;
	int sx=size[root[x]];
	int sy=size[root[y]];
	if(sx<sy) swap(x,y);
	Dfs(root[x],root[y]);
	father[y]=x;
}
int Q(int now,int k)
{
	if(now==0) return -1;
	int tmp=size[now]-size[to[now][1]];
	if(tmp==k) return id[now];
	else if(tmp<k) return Q(to[now][1],k-tmp);
	else return Q(to[now][0],k);
}
int main()
{
	cin >>n >>m;
	int x,y,q;
	char s[20];
	for(int i=1;i<MAXN;i++) laji[++top]=i;
	for(int i=1;i<MAXN;i++) father[i]=i; 
	for(int i=1;i<=n;i++) scanf("%d",&x),Ins(root[i],root[i],i,x,0);
	for(int i=1;i<=m;i++) scanf("%d %d",&x,&y),Link(x,y);
	cin >>q;
	while(q--)
	{
		scanf("%s %d %d",s+1,&x,&y);	
		if(s[1]=='Q') printf("%d\n",Q(root[F(x)],y));
		else Link(x,y);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值