您的位置:首页 > 其它

POJ-2985(树状数组 + 并查集 + 二分)

2015-02-26 19:55 246 查看
题目:http://poj.org/problem?id=2985

这题考察了两个点呢,组合并用到了并查集,求第K大的数用到了树状数组,刚开始WA了几次,发现是在组合并之后仅仅update(*, -1)了一次,因为是删除了两个组增加了一个组,应该是update(*, -1)两次,不细心啊。。。



#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAX	200005

int N, M, G;
int father[MAX] = {0};	//father[i]表示i所在group的首脑
int member[MAX] = {0};	//member[i]表示以i为首的group有多少个member
int group[MAX] = {0};	//group[i]表示成员有[i-lowbit(i)+1, i]个的group有多少个,

inline int lowbit(int x){ return x & -x; }
void update(int x, int v){
for(; x <= N; x += lowbit(x)){
group[x] += v;
}
}
int sum(int x)
{
int tot = 0;
for(; x; x -= lowbit(x)) tot += group[x];
return tot;
}
int query(int k)
{
int l = 0, r = N;
while(l + 1 < r){
int m = (l + r) >> 1;
if(sum(m) >= k) r = m;
else l = m;
}
return r;
}
int find(int x){
return x != father[x] ? father[x] = find(father[x]) : x;
}
void join(int x, int y)
{
int fx = find(x), fy = find(y);
if(fx == fy) return;

if(member[fx] > member[fy]) swap(fx, fy);
father[fx] =  fy;
update(member[fy], -1);
member[fy] += member[fx];
update(member[fx], -1);
member[fx] = 0;
update(member[fy], 1);
--G;
}
void init()
{
for(int i = 1; i <= N; ++i) father[i] = i;
for(int i = 1; i <= N; ++i) member[i] = 1;
G = N;
memset(group + 1, 0, N * sizeof(int));
for(int i = 0; (1 << i) <= N; ++i) group[1 << i] = N;
}

int main()
{
int c, x, y;
while(~scanf("%d%d", &N, &M)){
init();
while(M--){
scanf("%d%d", &c, &x);
if(c) printf("%d\n", query(G - x + 1));
else{
scanf("%d", &y);
join(x, y);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: