[HNOI2012]永无乡

link

十年前的省选题目,放到现在来看可谓足够简单。线段树合并模板加基础并查集,没什么好说的。

#include<cstdio>
//#define zczc
const int N=100010;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}
inline bool op(){
	char w=getchar();
	while(w!='Q'&&w!='B')w=getchar();
	return w=='B';
}

int m,n,q,cnt,f[N],root[N];
inline int find(int wh){return f[wh]==wh?wh:f[wh]=find(f[wh]);}

#define lc t[x].l
#define rc t[x].r
#define mid (l+r>>1)
struct node{int l,r,data,id;}t[N<<5];
inline void pushup(int x){
	t[x].data=t[lc].data+t[rc].data;
}
int insert(int x,int l,int r,int pl,int id){
	if(!x)x=++cnt;if(l==r)return t[x].data++,t[x].id=id,x;
	if(pl<=mid)lc=insert(lc,l,mid,pl,id);
	else rc=insert(rc,mid+1,r,pl,id);
	pushup(x);return x;
}
int merge(int x,int y,int l,int r){
	if(!x)return y;if(!y)return x;
	if(l==r)return t[x].data+=t[y].data,x;
	lc=merge(lc,t[y].l,l,mid);
	rc=merge(rc,t[y].r,mid+1,r);
	pushup(x);return x;
}
int work(int x,int l,int r,int want){
	if(want>t[x].data)return -1;
	if(l==r)return t[x].id;
	return t[lc].data>=want?work(lc,l,mid,want):work(rc,mid+1,r,want-t[lc].data);
}
#undef lc
#undef rc
#undef mid

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	
	read(m);read(n);int s1,s2;
	for(int i=1;i<=m;i++){f[i]=i;read(s1);root[i]=insert(0,1,m,s1,i);}
	for(int i=1;i<=n;i++){
		read(s1);read(s2);int f1=find(s1),f2=find(s2);if(f1==f2)continue;
		root[f1]=merge(root[f1],root[f2],1,m);f[f2]=f1; 
	}
	read(q);
	while(q--){
		if(op()){
			read(s1);read(s2);int f1=find(s1),f2=find(s2);if(f1==f2)continue;
			root[f1]=merge(root[f1],root[f2],1,m);f[f2]=f1; 
		}
		else{
			read(s1);read(s2);s1=find(s1);
			printf("%d\n",work(root[s1],1,m,s2));
		}
	}
	
	return 0;
}
posted @ 2022-03-26 15:11  Feyn618  阅读(35)  评论(0编辑  收藏  举报