HNOI2012 永无乡

题目链接:https://www.luogu.org/problemnew/show/P3224

splay启发式合并模板,小splay往大splay插,感性理解,一个点最多插logn次,插一次logn,n个点,nlognlogn~

#include<bits/stdc++.h>
using namespace std;
#define Inc(i,L,r) for(register int i=(L);i<=(r);++i)
const int N = 2e5+10;
int n,m,a[N];
int fa[N],rt[N];
inline int getfa(int x){//连通性用并查集维护 
	return x^fa[x]?fa[x]=getfa(fa[x]):x;
}
struct Splay{
	int p[N],ch[N][2];
	int cnt,vl[N],idx[N],siz[N];
	#define Ls(x) ch[x][0]
	#define rs(x) ch[x][1]
	#define maintain(x) siz[x]=siz[Ls(x)]+siz[rs(x)]+1
	inline void rotate(int x){
		int f=p[x],gf=p[f],tp=rs(f)==x,son=ch[x][!tp];
		ch[p[son]=f][tp]=son,maintain(f);
		ch[p[f]=x][!tp]=f,maintain(x);
		ch[p[x]=gf][rs(gf)==f]=x;
	}
	inline void splay(int x,int goal,int &root){
		if(x==goal)return ;
		while(p[x]^goal){
			if((p[p[x]]^goal)&&((rs(p[p[x]])==p[x])==(rs(p[x])==x)))rotate(p[x]);
			rotate(x);
		}
		if(!goal)root=x;
	}
	inline void newnode(int x,int k,int Fa,int Idx){
		idx[x]=Idx,siz[x]=1,vl[x]=k,p[x]=Fa;
	}
	inline void insert(int &x,int k,int Fa,int Idx,int &root){
		if(!x)return newnode(x=++cnt,k,Fa,Idx),splay(x,0,root),void();
		insert(ch[x][vl[x]<k],k,x,Idx,root);
	}
	inline int getrank(int x,int kth){
		while(x){
			if(siz[Ls(x)]+1==kth)return x;
			if(siz[Ls(x)]+1<kth)kth-=siz[Ls(x)]+1,x=rs(x);
			else x=Ls(x);
		}
		return -1;
	}
}sp;
inline void init(){
	scanf("%d%d",&n,&m);
	Inc(i,1,n)scanf("%d",&a[i]);
	Inc(i,1,n)fa[i]=i;
	Inc(i,1,m){
		int x,y;scanf("%d%d",&x,&y);
		fa[getfa(x)]=getfa(y);
	}
}
inline void prep(){
	Inc(i,1,n){
		int fx=getfa(i);
		sp.insert(rt[fx],a[i],0,i,rt[fx]);
	}
}
inline void Merge(int x,int &root){
	if(!x)return ;
	Merge(sp.Ls(x),root),Merge(sp.rs(x),root);
	sp.insert(root,sp.vl[x],0,sp.idx[x],root);
}
inline void merge(int x,int y){
	int fx=getfa(x),fy=getfa(y);
	if(sp.siz[rt[fx]]<sp.siz[rt[fy]])swap(fx,fy);
	fa[fy]=fx;
	Merge(rt[fy],rt[fx]);
}
inline void query(int x,int k){
	int p=sp.getrank(rt[getfa(x)],k);
	if(~p)cout<<sp.idx[p]<<"\n";
	else puts("-1");
}
inline void solv(){
	int T;scanf("%d",&T);
	while(T--){
		char op=getchar();while((op^'Q')&&(op^'B'))op=getchar();
		int x,k;scanf("%d%d",&x,&k);
		if(op=='Q')query(x,k);
		if(op=='B')merge(x,k);
	}
}
int main(){
	init();
	prep();
	solv();
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值