启发式合并
至今不知道时空复杂度怎么保证,从不证明算法复杂度,只会用大数据实测一下......
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<map>
using namespace std;
inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x)
{
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
inline void read(char &x)
{
for (x=nc();x!='B' && x!='Q';x=nc());
}
int n,m;
int idx[100005];
int fat[100005],w[100005];
int size,root[100005],ls[1800005],rs[1800005],sum[1800005];
inline int getfat(int u){
return u==fat[u]?u:fat[u]=getfat(fat[u]);
}
inline void insert(int &rt,int l,int r,int val)
{
if (!rt) rt=++size;
if (l==r){
sum[rt]=1;
return;
}
int mid=(l+r)>>1;
if (val<=mid)
insert(ls[rt],l,mid,val);
else
insert(rs[rt],mid+1,r,val);
sum[rt]=sum[ls[rt]]+sum[rs[rt]];
}
inline int merge(int x,int y)
{
if (!x) return y;
if (!y) return x;
ls[x]=merge(ls[x],ls[y]);
rs[x]=merge(rs[x],rs[y]);
sum[x]=sum[ls[x]]+sum[rs[x]];
return x;
}
inline int query(int rt,int l,int r,int k)
{
if (l==r) return l;
int mid=(l+r)>>1;
if (k<=sum[ls[rt]])
return query(ls[rt],l,mid,k);
else
return query(rs[rt],mid+1,r,k-sum[ls[rt]]);
}
int main()
{
int _x,_y,fx,fy,Q;
char order;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(m);
for (int i=1;i<=n;i++)
read(w[i]),idx[w[i]]=i;
for (int i=1;i<=n;i++)
fat[i]=i;
for (int i=1;i<=m;i++)
{
read(_x),read(_y);
fx=getfat(_x); fy=getfat(_y);
fat[fx]=fy;
}
for (int i=1;i<=n;i++)
insert(root[getfat(i)],1,n,w[i]);
read(Q);
while (Q--)
{
read(order);
if (order=='B')
{
read(_x); read(_y);
fx=getfat(_x); fy=getfat(_y);
if (fx!=fy)
{
fat[fx]=fy;
root[fy]=merge(root[fx],root[fy]);
}
}
else if (order=='Q')
{
read(_x); fx=getfat(_x); read(_y);
if (sum[root[fx]]<_y)
printf("-1\n");
else
printf("%d\n",idx[query(root[fx],1,n,_y)]);
}
}
return 0;
}