poj2985 The k-th Largest Group 【树状数组求第K大】

来源:互联网 发布:三维地理信息系统软件 编辑:程序博客网 时间:2024/05/22 07:48

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

题意:给你n,m,代表有n个集合,开始每个集合大小为1,接下来m个操作,每个操作先输入c,c==0则将x,y集合合并,c==0,输出第k大。

分析:集合和并可以用并查集,然后求第k大直接用树状数组。

代码:

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<string>#include<vector>#include<queue>#include<cmath>#include<stack>#include<set>#include<map>#define INF 0x3f3f3f3f#define Mn 200005#define Mm 2000005#define mod 1000000007#define CLR(a,b) memset((a),(b),sizeof((a)))#define CPY(a,b) memcpy ((a), (b), sizeof((a)))#pragma comment(linker, "/STACK:102400000,102400000")#define ul u<<1#define ur (u<<1)|1using namespace std;typedef long long ll;int bit[Mn];int n;int lowbit(int x) {    return x&(-x);}int sum(int x) {    int sum=0;    while(x>0) {        sum+=bit[x];        x-=lowbit(x);    }    return sum;}void push(int pos,int num) {    while(pos<=n) {        bit[pos]+=num;        pos+=lowbit(pos);    }}int kth(int k) {    int num=0;    int x=0;    for(int i=1<<18; i>0; i>>=1) {        num+=i;        if(num>=n||x+bit[num]>=k)            num-=i;        else x+=bit[num];    }    return num+1;}int pre[Mn];int find(int x) {    return x==pre[x]?pre[x]:pre[x]=find(pre[x]);}int num[Mn];int main() {    int m,c,x,y;    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++) {        pre[i]=i;        num[i]=1;    }    push(1,n);    int k=n;    for(int i=1;i<=m;i++) {        scanf("%d",&c);        if(c==0) {            scanf("%d%d",&x,&y);            int a=find(x);            int b=find(y);            if(a!=b) {                pre[a]=b;                push(num[a],-1);                push(num[b],-1);                num[b]+=num[a];                num[a]=0;                push(num[b],1);                k--;            }        } else {            scanf("%d",&x);            printf("%d\n",kth(k-x+1));        }    }    return 0;}


0 0
原创粉丝点击