H y p e r l i n k Hyperlink Hyperlink
https://www.luogu.com.cn/problem/P3224
D e s c r i p t i o n Description Description
给定一张有 n n n个点, m m m条边的无向图,每个点有一个排名 p i p_i pi
会合并一些块,每次询问 x x x所在的联通块第 k k k大的数
数据范围:
m
,
n
≤
1
0
5
,
q
≤
3
×
1
0
5
,
p
i
≤
n
m,n\leq 10^5,q\leq3\times 10^5,p_i\leq n
m,n≤105,q≤3×105,pi≤n
S o l u t i o n Solution Solution
显然我们可以用取值线段树来维护一个联通块
对于合并操作,直接上线段树合并即可
由于不用离散化,非常好写
时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
C o d e Code Code
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100010
#define LL long long
using namespace std;int n,rt[N],f[N],m,q,ls[N<<5],rs[N<<5],sum[N<<5],cnt,id[N<<5],x,y,fx,fy,res;
char s[10];
inline LL read()
{
char c;LL d=1,f=0;
while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
inline void Insert(int &k,int x,int d,int l=1,int r=n)
{
if(!k) k=++cnt;
if(l==r) {id[k]=d;sum[k]++;return;}
int mid=l+r>>1;
if(x<=mid) Insert(ls[k],x,d,l,mid);
else Insert(rs[k],x,d,mid+1,r);
sum[k]=sum[ls[k]]+sum[rs[k]];
return;
}
inline int Merge(int x,int y,int l=1,int r=n)
{
if(x==0) return y;if(y==0) return x;
if(l==r) {if(id[y]) {id[x]=id[y];sum[x]+=sum[y];}return x;}
int mid=l+r>>1;
ls[x]=Merge(ls[x],ls[y],l,mid);
rs[x]=Merge(rs[x],rs[y],mid+1,r);
sum[x]=sum[ls[x]]+sum[rs[x]];
return x;
}
inline int Query(int k,int pos,int l=1,int r=n)
{
if(sum[k]<pos||x==0) return 0;
if(l==r) return id[k];
int mid=l+r>>1;
if(pos<=sum[ls[k]]) return Query(ls[k],pos,l,mid);
else return Query(rs[k],pos-sum[ls[k]],mid+1,r);
}
signed main()
{
n=read();m=read();
for(register int i=1;i<=n;i++) f[i]=i,x=read(),Insert(rt[i],x,i);
for(register int i=1;i<=m;i++)
{
x=read();y=read();
fx=find(x);fy=find(y);
if(fx==fy) continue;
f[fy]=fx;
Merge(rt[fx],rt[fy]);
}
q=read();
while(q--)
{
scanf("%s",s);
if(s[0]=='Q')
{
x=read();y=read();
fx=find(x);
res=Query(rt[fx],y);
if(res==0) puts("-1");
else printf("%d\n",res);
}
if(s[0]=='B')
{
x=read();y=read();
fx=find(x);fy=find(y);
if(fx==fy) continue;
f[fy]=fx;
Merge(rt[fx],rt[fy]);
}
}
}