PKU 2985 The k-th Largest Group

PKU 2985 The k-th Largest Group

题目链接:http://poj.org/problem?id=2985

/**/ /*
题意:
    给定N(N <= 200000)个操作,每个操作是以下两种形式:
0 x y : 合并x所在的组和y所在的组,如果x和y同组,不合并。
1 k:输出第k大的组的元素个数。

解法:
树状数组 + 并查集

思路:
     将元素的个数对应树状数组的下标,每次合并操作,在树状
数组中对应两个集合大小的位置分别减1,两集合之后的位置+1,
询问操作只需要二分答案,然后每次统计比k大的数的个数判可行
即可。
*/


#include 
< iostream >

using   namespace  std;

#define  maxn 200010

int  c[maxn];
int  prev[maxn], num[maxn];
int  n;

int  lowbit( int  x)  {
    
return x & (-x);
}

void  add( int  pos,  int  num)  {
    
while(pos <= n) {
        c[pos] 
+= num;
        pos 
+= lowbit(pos);
    }

}


int  sum( int  pos)  {
    
int s = 0;
    
while(pos > 0{
        s 
+= c[pos];
        pos 
-= lowbit(pos);
    }

    
return s;
}


int  find( int  x)  {
    
int q = x;
    
while(x != prev[x]) {
        x 
= prev[x];
    }

    
return x;
}


void  Union( int  x,  int  y)  {
    x 
= find(x);
    y 
= find(y);

    
if(x != y) {
        
if(num[x] == num[y])
            add(num[x], 
-2);
        
else {
            add(num[x], 
-1);
            add(num[y], 
-1);
        }

        add(num[x] 
+ num[y], 1);

        
if(num[x] < num[y]) {
            prev[x] 
= y;
            num[y] 
+= num[x];
        }
else {
            prev[y] 
= x;
            num[x] 
+= num[y];
        }

    }

}



int  Query( int  k)  {
    
int l = 1;
    
int r = n;
    
int ans = 0;
    
int all = sum(n);
    
while(l <= r) {
        
int m = (l + r) >> 1;
        
if(k <= all - sum(m-1)) {
            l 
= m + 1;
            ans 
= m;
        }
else
            r 
= m - 1;
    }

    
return ans;
}


int  main()  {
    
int i, m;
    
int op, x, y;
    
while(scanf("%d %d"&n, &m) != EOF) {
        
for(i = 1; i <= n; i++{
            c[i] 
= 0;
            prev[i] 
= i;
            num[i] 
= 1;
        }

        add(
1, n);
        
while(m--{
            scanf(
"%d"&op);
            
if(op == 0{
                scanf(
"%d %d"&x, &y);
                Union(x, y);
            }
else {
                scanf(
"%d"&x);
                printf(
"%d\n", Query(x));
            }

        }


    }

    
return 0;
}

你可能感兴趣的:(PKU 2985 The k-th Largest Group)