【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≤ ...
随机推荐
- 用Delphi 实现WebService 转
一编写服务程序 第一步:File----->New----->Other------>WebServices----->Soap Server Application 选择IS ...
- 游戏开发Camera之Cinematic Camera-深度
人的视觉系统是二维的,它通过生理和心理的暗示来感知图像的深度,在现实世界中视觉系统会自动用深度线索depth cue来确定对象之间的距离游戏画面也是二维的,用x,y轴来定义,画面深度用z轴来定义,可以 ...
- Postman用法简介-Http请求模拟工具
在我们平时开发中,特别是需要与接口打交道时,无论是写接口还是用接口,拿到接口后肯定都得提前测试一下,这样的话就非常需要有一个比较给力的Http请求模拟工具,现在流行的这种工具也挺多的,像火狐浏览器插件 ...
- RTP, RTCP, RTSP 协议介绍
流媒体是边下载边播放的方式, 是视频会议.IP电话等应用场合的技术基础. 为什么TCP/IP协议就不能满足多媒体通信的要求呢?因为TCP有以下4个特点:1.TCP重传机制2.TCP ...
- tomacat 配置ssl协议
1.首先用jdk自带的工具keytool生成一个"服务器证书" a.命令行进入$JAVA_HOME/bin目录($JAVA_HOME为jdk的安装目录) b.输入:keytool ...
- 深入浅出node(4) 异步编程
一)函数式编程基础 二)异步编程的优势和难点 2.1 优势 2.2 难点 2.2.1 异常处理 2.2.2 函数嵌套过深 2.2.3 阻塞 2.2.4 多线程编程 2.2.5 异步转同步 三)异步编程 ...
- 一句话菜刀获取ip详细信息
<?php $ip="你要查的ip"; $url="http://ip.taobao.com/service/getIpInfo.php?ip=".$ip ...
- 【Android - V】之DrawerLayout的使用
DrawerLayout是Android V4包中的一个布局控件,用来实现一个抽屉样式的布局. DrawerLayout通过设置子视图的layout_gravity来决定子视图停靠在屏幕的哪个边缘外侧 ...
- Handler具体解释系列(四)——利用Handler在主线程与子线程之间互发消息
MainActivity例如以下: package cc.c; import android.app.Activity; import android.os.Bundle; import androi ...
- 【边做项目边学Android】小白会遇到的问题--This Android SDK requires Android Developer Toolkit version 23.0.0 or above
问题描写叙述: 上一篇讲到解决Appcompat_V7问题要减少adt版本号,于是就换旧版本号22.3.0啊,又一次打开Eclipse.立刻弹出: This Android SDK requires ...