POJ 2985 The k-th Largest Group(树状数组 并查集/查找第k大的数)
| Time Limit: 2000MS | Memory Limit: 131072K | |
| Total Submissions: 8690 | Accepted: 2847 |
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 ≤ N, M ≤ 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 ≤ i, j ≤ 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.
思路
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 200005;
int N,root[maxn],a[maxn],c[maxn];
int find(int x)
{
if (root[x] != x) root[x] = find(root[x]);
return root[x];
}
int find_kth(int x) //查找第k小的元素
{
int ans = 0,cnt = 0;
for (int i = 20;i >= 0;i--) //这里的20适当的取值,与MAX_VAL有关,一般取lg(MAX_VAL)
{
ans += (1 << i);
if (ans > N || cnt + c[ans] >= x)
ans -= (1 << i);
else
cnt += c[ans];
}
return ans + 1;
}
void upd(int i,int v)
{
while (i <= N)
{
c[i] += v;
i += i & -i;
}
}
int main()
{
int M;
while (~scanf("%d%d",&N,&M))
{
int tot = N;
memset(c,0,sizeof(c));
for (int i = 1;i <= N;i++) root[i] = i,a[i] = 1; //a[i]表示编号为i的Group大小
upd(1,N); //初始Group大小为1的有N个
while (M--)
{
int opt,x,y;
scanf("%d",&opt);
if (opt == 0)
{
scanf("%d%d",&x,&y);
x = find(x);
y = find(y);
if (x == y) continue;
upd(a[x],-1);
upd(a[y],-1); //x与y合并,则编号为x的Group与编号为y的Group大小减1
upd(a[x] + a[y],1); //大小为a[x]+a[y]的Group的大小增1
root[y] = x; //y的祖先节点为x;
a[x] += a[y]; //编号为x的Group大小增加a[y]
tot--; //并查集合并,则总元素减少1
}
else
{
scanf("%d",&x);
printf("%d\n",find_kth(x));
}
}
}
return 0;
}
POJ 2985 The k-th Largest Group(树状数组 并查集/查找第k大的数)的更多相关文章
- [BZOJ3038]上帝造题的七分钟2 树状数组+并查集
考试的时候用了两个树状数组去优化,暴力修改,树状数组维护修改后区间差值还有最终求和,最后骗了40分.. 这道题有好多种做法,求和好说,最主要的是开方.这道题过的关键就是掌握一点:在数据范围内,最多开方 ...
- poj 2985 The k-th Largest Group 树状数组求第K大
The k-th Largest Group Time Limit: 2000MS Memory Limit: 131072K Total Submissions: 8353 Accepted ...
- POJ2985 The k-th Largest Group[树状数组求第k大值+并查集||treap+并查集]
The k-th Largest Group Time Limit: 2000MS Memory Limit: 131072K Total Submissions: 8807 Accepted ...
- luogu 4145 花神游历各国 线段树/树状数组+并查集
此题一看便是RMQ问题,但是由于开平方的特殊操作,tag操作失效 此时发现特性:sqrt最多执行6此便使值到达1/0,此时可以剪枝不进行该操作,利用并查集到达特性找根,根代表还可以进行操作的点,再利用 ...
- SPOJ GSS4 Can you answer these queries IV ——树状数组 并查集
[题目分析] 区间开方+区间求和. 由于区间开方次数较少,直接并查集维护下一个不是1的数的位置,然后暴力修改,树状数组求和即可. 这不是BZOJ上上帝造题7分钟嘛 [代码] #include < ...
- CodeVS2492 上帝造题的七分钟2(树状数组+并查集)
传送门 树状数组模板题.注意优化,假设某个数的值已经是1了的话.那么我们以后就不用对他进行操作了,这个能够用并查集实现. 这道题还有个坑的地方,给出查询区间端点的a,b,有可能a>b. #inc ...
- BZOJ 3211 花神游历各国 (树状数组+并查集)
题解:首先,单点修改求区间和可以用树状数组实现,因为开平方很耗时间,所以在这个方面可以优化,我们知道,开平方开几次之后数字就会等于1 ,所以,用数组记录下一个应该开的数,每次直接跳到下一个不是1的数字 ...
- BZOJ3211 花神游历各国 【树状数组 + 并查集】
题目 输入格式 输出格式 每次x=1时,每行一个整数,表示这次旅行的开心度 输入样例 4 1 100 5 5 5 1 1 2 2 1 2 1 1 2 2 2 3 1 1 4 输出样例 101 11 1 ...
- [BZOJ3211]花神游历各国&&[BZOJ3038] 上帝造题的七分钟2 树状数组+并查集
3211: 花神游历各国 Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 4057 Solved: 1480[Submit][Status][Discu ...
随机推荐
- [PGM] I-map和D-separation
之前在概率图模型对概率图模型做了简要的介绍.此处介绍有向图模型中几个常常提到的概念,之前参考的多为英文资料,本文参考的是<概率图模型-原理与技术的>中译版本.很新的书,纸质很好,翻译没有很 ...
- variable-precision SWAR算法介绍
BITCOUNT命令是统计一个位数组中非0进制位的数量,数学上称作:”Hanmming Weight“ 目前效率最好的为variable-precision SWAR算法,可以常数时间内计算出多个字节 ...
- hihocoder1241 Best Route in a Grid
题目链接:hihocoder 1241 题意: n*n的格阵,每个方格内有一个数字.蚂蚁从左上角走到右下角,数字是零的方格不能走,只能向右向下走.蚂蚁走的路径上全部方格的的乘积为s,要使s低位0的个数 ...
- C++之父Bjarne Stroustrup提供的关于异常处理的建议
节选自<The C++ Programming Language> ——C++之父Bjarne Stroustrup 1. Don’t use exceptions wh ...
- Bete冲刺第四阶段
Bete冲刺第四阶段 今日工作: web: 昨晚搞得很晚,帮队友搞定了git的问题,仓库顿时干净多了,同时已经基本完成了基础功能的接口 ios: 导入并使用了改善交互的第三方开源库,修正路径BUG 目 ...
- iOS常用---NSArray,NSMutabuleArray
// 创建一个普通的数组,数组中可存储 id(任意)类型 NSArray *array =[[NSArray alloc]initWithObjects:",@"c" ...
- Android基础知识总结
四大组件之一活动 活动状态 运行状态:活动处于栈顶 暂停状态:活动不处于栈顶,但仍然可见 停止状态:完全不可见 销毁状态:离开返回栈 生存期 onCreate() onStart():不可见到可见调用 ...
- [转]oracle学习入门系列之五内存结构、数据库结构、进程
原文地址:http://www.2cto.com/database/201505/399285.html 1 Oracle数据库结构 关于这个话题,网上一搜绝对一大把,更别提书籍上出现的了,还有很多大 ...
- 【BZOJ 1178】【APIO 2009】CONVENTION会议中心
http://www.lydsy.com/JudgeOnline/problem.php?id=1178 这道题想了好久没想明白,倍增数组通过看题解很快就明白了,但是一小段区间内应有的最多线段数一直不 ...
- 【POJ 1113】Wall
http://poj.org/problem?id=1113 夏令营讲课时的求凸包例题,据说是PKUSC2015的一道题 我WA两次错在四舍五入上了(=゚ω゚)ノ #include<cmath& ...