题意
每个数有一个排名,要求维护两种操作:
-
把(x)和(y)所在的联通块连载一起。
-
查询(x)所在联通块的(k)小值。
思路
思路显然,并查集维护连通性,动态开点权值线段树合并维护查询。这道题污染了HNOI。
代码
#include <bits/stdc++.h>
using namespace std;
namespace StandardIO {
template<typename T> inline void read (T &x) {
x=0;T f=1;char c=getchar();
for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
x*=f;
}
template<typename T> inline void write (T x) {
if (x<0) putchar('-'),x=-x;
if (x>=10) write(x/10);
putchar(x%10+'0');
}
}
using namespace StandardIO;
namespace Solve {
const int N=100001;
int n,m,q;
int val[N],trn[N];
int f[N];
int cnt;
struct node {
int lc,rc;
int l,r,val;
} tree[N*40];
int root[N];
inline void pushup (int pos) {
tree[pos].val=tree[tree[pos].lc].val+tree[tree[pos].rc].val;
}
void build (int rt,int l,int r,int &pos) {
if (!pos) pos=++cnt;
tree[pos].l=l,tree[pos].r=r,tree[pos].val=0;
if (l==r) return tree[pos].val=(l==val[rt]),void();
int mid=(l+r)>>1;
if (val[rt]<=mid) build(rt,l,mid,tree[pos].lc);
else build(rt,mid+1,r,tree[pos].rc);
pushup(pos);
}
int query (int k,int pos) {
if (tree[pos].l==tree[pos].r) return tree[pos].l;
if (k<=tree[tree[pos].lc].val) return query(k,tree[pos].lc);
return query(k-tree[tree[pos].lc].val,tree[pos].rc);
}
void Tmerge (int &x,int y) {
if (!x) return x=y,void();
if (!y) return;
if (tree[x].l==tree[x].r) return tree[x].val+=tree[y].val,void();
Tmerge(tree[x].lc,tree[y].lc),Tmerge(tree[x].rc,tree[y].rc);
pushup(x);
}
inline int find (int x) {
return (f[x]==x)?x:f[x]=find(f[x]);
}
inline void merge (int x,int y) {
x=find(x),y=find(y);
if (f[x]!=y) f[x]=y,Tmerge(root[y],root[x]);
}
void dfs (int now) {
cout<<tree[now].l<<' '<<tree[now].r<<endl;
if (tree[now].lc) cout<<"lc:",dfs(tree[now].lc);
if (tree[now].rc) cout<<"rc:",dfs(tree[now].rc);
}
inline void MAIN () {
read(n),read(m);
for (register int i=1; i<=n; ++i) {
read(val[i]),trn[val[i]]=i,f[i]=i,build(i,1,n,root[i]);
}
for (register int i=1; i<=m; ++i) {
int x,y;
read(x),read(y);
merge(x,y);
}
read(q);
while (q--) {
char op;int x,y;
cin>>op,read(x),read(y);
if (op=='B') {
merge(x,y);
} else {
if (tree[root[find(x)]].val<y) write(-1);
else write(trn[query(y,root[find(x)])]);
putchar('
');
}
}
}
}
int main () {
Solve::MAIN();
}