POJ2985 The k-th Largest Group[树状数组求第k大值 并查集]

The k-th Largest Group

Time Limit: 2000MS   Memory Limit: 131072K
Total Submissions: 8807   Accepted: 2875

Description

Newman likes playing with cats. He possesses lots of cats in his home. Because the number of cats is really huge, Newman wants to group some of the cats. To do that, he first offers a number to each of the cat (1, 2, 3, …, n). Then he occasionally combines the group cat i is in and the group cat j is in, thus creating a new group. On top of that, Newman wants to know the size of the k-th biggest group at any time. So, being a friend of Newman, can you help him?

Input

1st line: Two numbers N and M (1 ≤ NM ≤ 200,000), namely the number of cats and the number of operations.

2nd to (m + 1)-th line: In each line, there is number C specifying the kind of operation Newman wants to do. If C = 0, then there are two numbers i and j (1 ≤ ij ≤ n) following indicating Newman wants to combine the group containing the two cats (in case these two cats are in the same group, just do nothing); If C = 1, then there is only one number k (1 ≤ k ≤ the current number of groups) following indicating Newman wants to know the size of the k-th largest group.

Output

For every operation “1” in the input, output one number per line, specifying the size of the kth largest group.

Sample Input

10 10
0 1 2
1 4
0 3 4
1 2
0 5 6
1 1
0 7 8
1 1
0 9 10
1 1

Sample Output

1
2
2
2
2

Hint

When there are three numbers 2 and 2 and 1, the 2nd largest number is 2 and the 3rd largest number is 1.

Source

POJ Monthly--2006.08.27, zcgzcgzcg


并查集维护连通分量大小,树状数组求cc中第k大值

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=2e5+5;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
    return x*f;
}
int n,m,op,x,y,k;
int fa[N],size[N],tot=0;
inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}

int c[N];
inline int lowbit(int x){return x&-x;}
inline void add(int p,int v){
    for(;p<=n;p+=lowbit(p)) c[p]+=v;
}
inline int sum(int p){
    int res=0;
    for(;p>0;p-=lowbit(p)) res+=c[p];
    return res;
}
inline int kth(int k){
    int x=0,cnt=0;
    for(int i=16;i>=0;i--){
        x+=(1<<i);
        if(x>=n||cnt+c[x]>=k) x-=(1<<i);
        else cnt+=c[x];
    }
    return x+1;
}

int main(){
    n=read();m=read();
    for(int i=1;i<=n;i++) fa[i]=i,size[i]=1,tot++;
    add(1,n);
    for(int i=1;i<=m;i++){
        op=read();
        if(!op){
            x=read();y=read();
            int f1=find(x),f2=find(y);
            if(f1!=f2){
                fa[f1]=f2;
                add(size[f1],-1);
                add(size[f2],-1);
                size[f2]+=size[f1];
                add(size[f2],1);
                tot--;
            }
        //    printf("%d %d %d %d\n",f1,f2,size[f1],size[f2]);
        }else{
            k=tot-read()+1;//printf("k %d\n",k);
            printf("%d\n",kth(k));
        }
    }
}
时间: 2024-10-26 23:49:09

POJ2985 The k-th Largest Group[树状数组求第k大值 并查集]的相关文章

hdu 2985 The k-th Largest Group 树状数组求第K大

The k-th Largest Group Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8353   Accepted: 2712 Description Newman likes playing with cats. He possesses lots of cats in his home. Because the number of cats is really huge, Newman wants to g

HDU 5249 离线树状数组求第k大+离散化

KPI Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1160    Accepted Submission(s): 488 Problem Description 你工作以后, KPI 就是你的全部了. 我开发了一个服务,取得了很大的知名度.数十亿的请求被推到一个大管道后同时服务从管头拉取请求.让我们来定义每个请求都有一个重要值.我的

hdu2852 KiKi&#39;s K-Number 树状数组求第k大数

//再求第k大数时只需要getsum(b-1)<getsum(a)+k<=getsum(b) //b就是a的第k大数 //又gesum(b-1)<=getsum(b)则可以用二分查找来做 #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=100010; int tree[maxn]; int lowbit(int i) {

树状数组求第K小值 (spoj227 Ordering the Soldiers &amp;&amp; hdu2852 KiKi&#39;s K-Number)

题目:http://www.spoj.com/problems/ORDERS/ and http://acm.hdu.edu.cn/showproblem.php?pid=2852 题意:spoj227:告诉每个位置前面有多少个数比当前位置小,求出原序列.hdu2852:设计一个容器,支持几种操作:增加/删除元素,求容器中比a大的数中第k小的数是多少. 分析:两个题思路都是求数组里面的第K小的数.开始一直在找O(N*logN)的方法,后来发现O(N*logN*logN)也是可以过的...两步:和

zoj 3635 Cinema in Akiba (树状数组求第K大)

Cinema in Akiba Cinema in Akiba (CIA) is a small but very popular cinema in Akihabara. Every night the cinema is full of people. The layout of CIA is very interesting, as there is only one row so that every audience can enjoy the wonderful movies wit

*HDU2852 树状数组(求第K小的数)

KiKi's K-Number Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3864    Accepted Submission(s): 1715 Problem Description For the k-th number, we all should be very familiar with it. Of course,to

树状数组求第K大(From CLJ)

int ret=0; for(int p=1<<log2[n];p;p>>=1) if(a[ret+p]<=kth) kth-=a[ret+=p]; return ret;

POJ3928 Pingpong(统计比 K 小的个数 + 树状数组)

Ping pong Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2691   Accepted: 996 Description N(3<=N<=20000) ping pong players live along a west-east street(consider the street as a line segment). Each player has a unique skill rank. To im

【转载】【树状数组区间第K大/小】

原帖:http://www.cnblogs.com/zgmf_x20a/archive/2008/11/15/1334109.html 回顾树状数组的定义,注意到有如下两条性质: 一,c[ans]=sum of A[ans-lowbit(ans)+1 ... ans];二,当ans=2^k时, c[ans]=sum of A[1 ... ans]; 下面说明findK(k)如何运作:1,设置边界条件ans,ans'<maxn且cnt<=k:2,初始化cnt=c[ans],其中ans=2^k且k