[HNOI2012]永无乡
十年前的省选题目,放到现在来看可谓足够简单。线段树合并模板加基础并查集,没什么好说的。
#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;
}
一如既往,万事胜意