pku2985 The k-th Largest Group
题意:初始化状态为N个含单一元素的集合,动态合并任意两个集合,查询第ith大的集合的大小
分析:以虚二叉树做辅助结构找出第ith大的集合的大小
#include <iostream>
#include <algorithm>
using namespace std;
#define MAXN 200001
int v[MAXN],N,M,pnt[MAXN],son[3*MAXN];
//v[i]第i只猫所在组的猫的数量,范围在1~N之间;son[u]表示以结点u为根的子树的结点数
void insert(int num,int k){
int l=1,r=N,m,u=1;
while(l<r){
m=(l+r)/2;
son[u]+=k;
if(num<=m){
r=m;
u=u*2;
}
else{
l=m+1;
u=u*2+1;
}
}
son[u]+=k;
}
int find(int ith){
int l=1,r=N,u=1,m;
while(l<r){
m=(l+r)/2;
if(son[2*u+1]>=ith){
l=m+1;
u=u*2+1;
}
else{
ith-=son[2*u+1];
r=m;
u=u*2;
}
}
return l;
}
void init(){
int i;
for(i=1;i<=N;i++){
pnt[i]=i;
v[i]=1;
insert(v[i],1);
}
}
int fs(int i){
if(pnt[i]==i)
return i;
pnt[i]=fs(pnt[i]);
return pnt[i];
}
int main(){
int q,a,b,x,y,ith;
while(scanf("%d%d",&N,&M)!=EOF){
init();
while(M--){
scanf("%d",&q);
if(q==0){
scanf("%d%d",&a,&b);
x=fs(a);
y=fs(b);
if(x!=y){
pnt[x]=y;
insert(v[x],-1);
insert(v[y],-1);
v[y]+=v[x];
insert(v[y],1);
}
}
else{
scanf("%d",&ith);
printf("%d\n",find(ith));
}
}
}
return 0;
}
#include <algorithm>
using namespace std;
#define MAXN 200001
int v[MAXN],N,M,pnt[MAXN],son[3*MAXN];
//v[i]第i只猫所在组的猫的数量,范围在1~N之间;son[u]表示以结点u为根的子树的结点数
void insert(int num,int k){
int l=1,r=N,m,u=1;
while(l<r){
m=(l+r)/2;
son[u]+=k;
if(num<=m){
r=m;
u=u*2;
}
else{
l=m+1;
u=u*2+1;
}
}
son[u]+=k;
}
int find(int ith){
int l=1,r=N,u=1,m;
while(l<r){
m=(l+r)/2;
if(son[2*u+1]>=ith){
l=m+1;
u=u*2+1;
}
else{
ith-=son[2*u+1];
r=m;
u=u*2;
}
}
return l;
}
void init(){
int i;
for(i=1;i<=N;i++){
pnt[i]=i;
v[i]=1;
insert(v[i],1);
}
}
int fs(int i){
if(pnt[i]==i)
return i;
pnt[i]=fs(pnt[i]);
return pnt[i];
}
int main(){
int q,a,b,x,y,ith;
while(scanf("%d%d",&N,&M)!=EOF){
init();
while(M--){
scanf("%d",&q);
if(q==0){
scanf("%d%d",&a,&b);
x=fs(a);
y=fs(b);
if(x!=y){
pnt[x]=y;
insert(v[x],-1);
insert(v[y],-1);
v[y]+=v[x];
insert(v[y],1);
}
}
else{
scanf("%d",&ith);
printf("%d\n",find(ith));
}
}
}
return 0;
}