【POJ2985】【Treap + 并查集】The k-th Largest Group
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.
Source
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <utility>
#include <iomanip>
#include <string>
#include <cmath>
#include <queue>
#include <assert.h>
#include <map>
#include <ctime>
#include <cstdlib> const int N = + ;
const int SIZE = ;//块状链表的大小
const int M = + ;
using namespace std;
struct TREAP{
struct Node{
int fix, size;
int val;
Node *ch[];
}mem[N], *root;
struct mem_poor{//内存池
queue<Node>Q;
void push(Node *t){//消除指针t所占用的地址
Q.push((*t));
}
Node* get(){
Node* t = &Q.front();
Q.pop();
return t;
}
}poor;
int tot, size;
//大随机
void init(){
// for (int i = 0; i <= 200000 + 5; i++)
//poor.Q.push(mem[i]);
size = ;
tot = ;
}
int BIG_RAND(){return rand();}
Node *NEW(){
Node *p = new Node;
p->fix = rand();//BIG_RAND();
p->size = ;
p->ch[] = p->ch[] = NULL;
return p;
}
//将t的d节点换到t
void rotate(Node *&t, int d){
Node *p = t->ch[d];
t->ch[d] = p->ch[d ^ ];
p->ch[d ^ ] = t;
t->size = ;
if (t->ch[] != NULL) t->size += t->ch[]->size;
if (t->ch[] != NULL) t->size += t->ch[]->size;
p->size = ;
if (p->ch[] != NULL) p->size += p->ch[]->size;
if (p->ch[] != NULL) p->size += p->ch[]->size;
t = p;
return;
}
void insert(Node *&t, int val){
//插入
if (t == NULL){
t = NEW();
t->val = val;
//size++;
return;
}
//大的在右边,小的在左边
int dir = (val >= t->val);
insert(t->ch[dir], val);
//维护最大堆的性质
if (t->ch[dir]->fix > t->fix) rotate(t, dir);
t->size = ;
if (t->ch[] != NULL) t->size += t->ch[]->size;
if (t->ch[] != NULL) t->size += t->ch[]->size;
}
//在t的子树中找到第k小的值
int kth(Node *t, int k){
if (t == NULL || k<= || k > t -> size) return ;
if (t->size == ) return t->val;
int l = ;//t的左子树中有多少值
if (t->ch[] != NULL) l += t->ch[]->size;
if (k == (l + )) return t->val;
if (k <= l) return kth(t->ch[], k);
else return kth(t->ch[], k - (l + ));
}
/*int find(Node *t, int val){
if (t == NULL) return 0;
int l = 0;//累加值
if (t->ch[0] != NULL) l += t->ch[0]->size;
if (val == t->val) return l + 1;
else if (val < t->val) return find(t->ch[0], val);
else return l + 1 + find(t->ch[1], val);
}*/
//找到值为val的节点
/*Node *&get(Node *&t, int val){
//if (t == NULL) return NULL;
if (val == t->val) return t;//根结点是,没办法 if (t->ch[0] != NULL && t->ch[0]->val == val) return t;
if (t->ch[1] != NULL && t->ch[1]->val == val) return t; if (val < t->val) return get(t->ch[0], val);
else return get(t->ch[1], val);
}*/
/*void update(Node *&t){
if (t == NULL) return;
update(t->ch[0]);
update(t->ch[1]);
t->size = 1;
if (t->ch[0] != NULL) t->size += t->ch[0]->size;
if (t->ch[1] != NULL) t->size += t->ch[1]->size;
}*/
void Delete(Node* &t,int x){
int d;
if (x == t->val) d = -;
else d = (x > t->val);
if (d == -){
Node *tmp = t;
if(t->ch[] == NULL){
t = t->ch[];
//poor.push(tmp);
delete tmp;
tmp = NULL;
}else if(t->ch[] == NULL){
t = t->ch[];
//poor.push(tmp);
delete tmp;
tmp = NULL;
}else{
int k = t->ch[]->fix > t->ch[]->fix ? : ;
//int k = 1;
rotate(t,k);
Delete(t->ch[k ^ ],x);
}
}else Delete(t->ch[d],x);
if (t!=NULL){
t->size = ;
if (t->ch[] != NULL) t->size += t->ch[]->size;
if (t->ch[] != NULL) t->size += t->ch[]->size;
}
}
/*void print(Node *t){
if (t == NULL) return;
print(t->ch[0]);
printf("%d ", t->val);
print(t->ch[1]);
}*/
}treap;
/*int Scan() {
int res = 0, ch, flag = 0;
if((ch = getchar()) == '-') //判断正负
flag = 1;
else if(ch >= '0' && ch <= '9') //得到完整的数
res = ch - '0';
while((ch = getchar()) >= '0' && ch <= '9' )
res = res * 10 + ch - '0';
return flag ? -res : res;
} */
int parent[N], n ,m;
int find(int x){return parent[x] < ? x : parent[x] = find(parent[x]);} void init(){
treap.init();
treap.root = NULL;
//memset(parent, -1, sizeof(parent));
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++) parent[i] = -;
//n = Scan();
//m = Scan();
//for (int i = 1; i <= n; i++) treap.insert(treap.root, 1);
}
void work(){
for (int i = ; i <= m; i++){
int t;
//t = Scan();
scanf("%d", &t);
if (t == ){
int x, y;
scanf("%d%d", &x, &y);
//x = Scan();y = Scan();
x = find(x);
y = find(y);
if (x == y) continue;
if (parent[x] < -) treap.Delete(treap.root, -parent[x]);
if (parent[y] < -) treap.Delete(treap.root, -parent[y]);
treap.insert(treap.root, -(parent[x] + parent[y]));
parent[y] += parent[x];
parent[x] = y;
}else{
int k;
scanf("%d", &k);
//k = Scan();i
if (treap.root == NULL || k > treap.root->size) {printf("1\n");continue;}
k = treap.root->size - k + ;
printf("%d\n", treap.kth(treap.root, k));
}
}
} int main(){
int T;
srand(time());
#ifdef LOCAL
freopen("data.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
init();
work();
//debug();
return ;
}
【POJ2985】【Treap + 并查集】The k-th Largest Group的更多相关文章
- POJ2985 The k-th Largest Group[树状数组求第k大值+并查集||treap+并查集]
The k-th Largest Group Time Limit: 2000MS Memory Limit: 131072K Total Submissions: 8807 Accepted ...
- BZOJ 2733 [HNOI2012]永无乡(启发式合并+Treap+并查集)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2733 [题目大意] 给出n个点,每个点都有自己的重要度,现在有连边操作和查询操作, 查 ...
- 【BZOJ1604】[Usaco2008 Open]Cow Neighborhoods 奶牛的邻居 Treap+并查集
[BZOJ1604][Usaco2008 Open]Cow Neighborhoods 奶牛的邻居 Description 了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000) ...
- P1197 [JSOI2008]星球大战 并查集 反向
题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧 ...
- Codeforces#514E(贪心,并查集)
#include<bits/stdc++.h>using namespace std;long long w[100007],sum[100007];int fa[100007],degr ...
- POJ2985 The k-th Largest Group (并查集+treap)
Newman likes playing with cats. He possesses lots of cats in his home. Because the number of cats is ...
- [poj-2985]The k-th Largest Group_Treap+并查集
The k-th Largest Group poj-2985 题目大意:给你n只猫,有两种操作:1.将两只猫所在的小组合并.2.查询小组数第k大的小组的猫数. 注释:1<=n,m<=20 ...
- BZOJ 2733: [HNOI2012]永无乡(treap + 启发式合并 + 并查集)
不难...treap + 启发式合并 + 并查集 搞搞就行了 --------------------------------------------------------------------- ...
- 【bzoj1604】[Usaco2008 Open]Cow Neighborhoods 奶牛的邻居 旋转坐标系+并查集+Treap/STL-set
题目描述 了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000)只奶牛,你会发现她们已经结成了几个“群”.每只奶牛在吃草的时候有一个独一无二的位置坐标Xi,Yi(l≤Xi,Yi≤ ...
随机推荐
- myeclipse如何修改Web项目名称
1. 使用myeclipse进行Web项目开发时,有时候项目名称重命名了,但是WEB项目在tomcat里边的名称还是原来的名称,是需要重新命名的.下边详细介绍一下如果和修改web项目名称,myecli ...
- 《Linear Algebra and Its Applications》-chaper4-向量空间-子空间、零空间、列空间
在线性代数中一个非常重要的概念就是向量空间R^n,这一章节将主要讨论向量空间的一系列性质. 一个向量空间是一些向量元素构成的非空集合V,需要满足如下公理: 向量空间V的子空间H需要满足如下三个条件: ...
- lightoj 1033 区间dp
题目链接:http://lightoj.com/volume_showproblem.php?problem=1033 #include <cstdio> #include <cst ...
- dp poj 1080 Human Gene Functions
题目链接: http://poj.org/problem?id=1080 题目大意: 给两个由A.C.T.G四个字符组成的字符串,可以在两串中加入-,使得两串长度相等. 每两个字符匹配时都有个值,求怎 ...
- 关于平移的 scrollTo和scrollBy的区别
这几天在项目中要求一部分布局实现整体偏移的效果 在网上查了下我使用来ScrollBy(x,y)方法 他的意思是将view实现整体偏移 而ScollTo(x,y)则是将原点偏移到相应指定的位置即 移 ...
- ecshop判断搜索引擎是否为蜘蛛
<?php /** * 判断是否为搜索引擎蜘蛛 * * @access public * @return string */ function is_spider($record = true) ...
- flipsnap--手机屏幕水平滑动框架
在很多手机应用中,大家都会见过这样一种效果:当手指横向滑动屏幕时,屏幕上的页面会向左或向右滑动. 下面介绍一下当用HTML5+CSS3开发手机应用时解决这类效果的一款js框架:flipsnap. fl ...
- Unit Test单元测试时如何模拟HttpContext
参考文章:http://blog.csdn.net/bclz_vs/article/details/6902638 http://www.cnblogs.com/PurpleTide/archive/ ...
- Spark1.0.0 监测方法
Spark1.0.0能够通过下面几种方式来对Spark应用程序进行监控: Spark应用程序的WebUI或者Spark Standalone的集群监控 指标,然后通过支持指标收集的集群监控 ...
- nginx代理人server结合tomcat采用
相信非常多人都听过nginx,这个小巧的东西慢慢地在吞食apache和IIS的份额.那到底它有什么作用呢?可能非常多人未必了解. 说到反向代理,可能非常多人都听说,但详细什么是反向代理,非常多人预计就 ...