POJ2985 The k-th Largest Group(treap+并查集)
来源:互联网 发布:软件人才外包公司ren 编辑:程序博客网 时间:2024/06/06 08:32
题目链接
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 100 1 21 40 3 41 20 5 61 10 7 81 10 9 101 1
Sample Output
12222
题目大意:给定N只猫,序号从一到N,一开始每个都是一组,然后对这群猫进行操作,可以把两只猫合成一组,然后可以查询第K大的组里有几只猫。
并查集加treap,对于每一次合并,在treap里分别将两元素删除,然后用并查集将其合并,在将合并后的结果加入treap树即可。
代码如下:
#include <iostream>#include <string.h>#include <stdlib.h>#include <algorithm>#include <stdio.h>using namespace std;const int N=200005;struct node{ int l; int r; int val; int ran; int num; int w;}tree[N];struct query{ int c; int a,b;}in[N];int pre[N];//并查集int s,root;int fin(int x)//并查集查找{ if(x!=pre[x]) pre[x]=fin(pre[x]); return pre[x];}void join(int x,int y)//并查集合并函数{ int fx=fin(x),fy=fin(y); if(fx!=fy) { pre[fy]=fx; }}void lturn(int &k){ int t=tree[k].r; tree[k].r=tree[t].l; tree[t].l=k; tree[t].num=tree[k].num; tree[k].num=tree[tree[k].l].num+tree[tree[k].r].num+tree[k].w; k=t;}void rturn(int &k){ int t=tree[k].l; tree[k].l=tree[t].r; tree[t].r=k; tree[t].num=tree[k].num; tree[k].num=tree[tree[k].l].num+tree[tree[k].r].num+tree[k].w; k=t;}void ins(int &k,int x){ if(k==0) { s++; k=s; tree[k].val=x; tree[k].num=tree[k].w=1; tree[k].ran=rand(); return ; } tree[k].num++; if(tree[k].val==x) tree[k].w++; else if(tree[k].val>x) { ins(tree[k].l,x); if(tree[tree[k].l].ran<tree[k].ran) rturn(k); } else { ins(tree[k].r,x); if(tree[tree[k].r].ran<tree[k].ran) lturn(k); }}void del(int &k,int x){ if(k==0) return; if(tree[k].val==x) { if(tree[k].w>1) { tree[k].num--; tree[k].w--; return; } if(tree[k].l*tree[k].r==0) k=tree[k].l+tree[k].r; else if(tree[tree[k].l].ran<tree[tree[k].r].ran) { rturn(k); del(k,x); } else { lturn(k); del(k,x); } } else if(tree[k].val<x) { tree[k].num--; del(tree[k].r,x); } else { tree[k].num--; del(tree[k].l,x); }}int queryknum(int k,int x){ if(k==0) return 0; if(x<=tree[tree[k].l].num) return queryknum(tree[k].l,x); else if(x>tree[tree[k].l].num+tree[k].w) return queryknum(tree[k].r,x-tree[tree[k].l].num-tree[k].w); else return tree[k].val;}int main(){ int data[N]; int n,m; memset(tree,0,sizeof(tree)); memset(data,0,sizeof(data)); memset(in,0,sizeof(in)); memset(pre,0,sizeof(pre)); scanf("%d %d",&n,&m); root=0; s=0; for(int i=1;i<=n;i++) { pre[i]=i; data[i]=1; ins(root,1); } for(int i=1;i<=m;i++) { scanf("%d",&in[i].c); if(in[i].c==0) scanf("%d %d",&in[i].a,&in[i].b); else scanf("%d",&in[i].a); } int total=n; for(int i=1;i<=m;i++) { if(in[i].c==0) { int x=fin(in[i].a); int y=fin(in[i].b); if(x!=y) { total--;//两元素合并,树内的总元素数目减1 del(root,data[x]); del(root,data[y]); join(x,y);//x是y的父节点 data[x]+=data[y];//更改后的元素 ins(root,data[x]); } } if(in[i].c==1) { printf("%d\n",queryknum(root,total-in[i].a+1));//查询为第K大的元素,所以倒过来查找,将treap插入过程的方向更改也可 } } return 0;}
- POJ2985 The k-th Largest Group(treap+并查集)
- [Treap]poj2985 The k-th Largest Group
- POJ 2985 The k-th Largest Group 第k大数 Treap / 树状数组 + 并查集
- POJ2985 The k-th Largest Group
- POJ2985 The k-th Largest Group
- POJ2985 The k-th Largest Group(Splay)
- poj2985 The k-th Largest Group
- poj 2985 The k-th Largest Group (Treap+并查集)
- poj2985(名次树(treap))找第k大 The k-th Largest Group
- Treap树(并查集 + 树堆)POJ —— 2985 The k-th Largest Group
- POJ 2985 The k-th Largest Group [并差集+treap]
- poj 2985 The k-th Largest Group 并查集+树状数组求第k大
- poj 2985 并查集+线段树 线段树求第k大数 The k-th Largest Group
- POJ2985 The k-th Largest Group(平衡树查询第K大)
- poj2985 The k-th Largest Group 【树状数组求第K大】
- PKU2985(The k-th Largest Group)线段树+并查集
- poj 2985 The k-th Largest Group/并查集+sbt
- poj 2985 The k-th Largest Group(线段树+并查集)
- JavaSE 异常、集合
- Activiti 历史流程图高亮显示
- ShaderLab: Properties
- 执行shell脚本时,遇到需要输入yes/no的时候,怎么自动化完成输入呢?
- msql的root账号忘记密码,修改root密码'mysqld_safe'
- POJ2985 The k-th Largest Group(treap+并查集)
- [Hdu] 4417 Super Mario (主席树模板题)
- java各种进制之间的相互转化
- 2017.08.18【NOIP提高组】模拟赛B组 沙耶的玩偶(doll)
- asp.net c# 异步日志通用类(1)
- Hibernate的悲观锁、乐观锁
- 代码详解の使用CountDownLatch解决面试问题:T1和T2线程执行计算,T3线程计算结果的统计
- CodeForces
- C++基本语法,入门及提高(5)