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 ;
}

你可能感兴趣的:(group)