POJ2985 The k-th Largest Group(Splay)

原创 2015年11月21日 16:09:10

有n组猫,m个操作。初始的时候每组猫有一只,有两种操作,可以把两组猫合并为一组,或者查询猫数第k多的组。

对于合并猫我们开一个并查集,检查那些已经在一个集合中的猫。首先在splay树中插入每组猫的数,当合并的时候,就从树中删去那两组猫,在插入它们的和。为了方便删除,在初始化的时候要插入0和n+1两个节点。

#include<cstdio>
#include<cctype>
#define MAXN 200010
void GET(int &t)
{
	char c;
	t = 0;
	do{c = getchar();}while(!isdigit(c));
	while(isdigit(c)){t = t*10+c-'0'; c = getchar();}
}
int fa[MAXN],sz[MAXN],cnt[MAXN],tot,root,ch[MAXN][2],v[MAXN],n,m,op,sat[MAXN],amount[MAXN];
int find(int x)
{
	if(sat[x] == x) return sat[x];
	else return sat[x] = find(sat[x]);
}
void update(int x)
{
	sz[x] = sz[ch[x][0]]+sz[ch[x][1]]+cnt[x];
}
void rotate(int x)
{
	int y = fa[x],z = fa[y],f = (ch[y][1]==x);
	ch[y][f] = ch[x][!f];
	if(ch[y][f]) fa[ch[y][f]] = y;
	ch[x][!f] = y,fa[y] = x;
	fa[x] = z;
	if(z) ch[z][ch[z][1]==y] = x;
	update(y);
}
void splay(int x,int goal)
{
	for(int y; (y=fa[x])!=goal; rotate(x))
	{
		int z = fa[y];
		if(z != goal)
		{
			if((ch[z][0]==y)==(ch[y][0]==x)) rotate(y);
			else rotate(x);
		}
	}
	if(goal == 0) root = x;
	update(x);
}
void insert(int val)
{
	int x = root,y = 0,f = 0;
	while(x != 0)
	{
		if(v[x] == val) {++cnt[x]; break;}
		f = v[x]<val;
		y = x;
		x = ch[x][f];
	}
	if(x == 0)
	{
		x = ++tot;
		v[x] = val;
		sz[x] = cnt[x] = 1;
		fa[x] = y;
		if(y) ch[y][f] = x;
	}
	splay(x,0);
}
int nxt(int val,bool flag)
{
	int x = root,y = 0;
	while(x != 0)
	{
		y = x;
		if(v[x] == val) break;
		x = ch[x][v[x]<val];
	}
	if((v[y]>val&&flag==1)||(v[y]<val&&flag==0)) return y;
	splay(y,0);
	int tmp = ch[y][flag];
	while(ch[tmp][!flag])
		tmp = ch[tmp][!flag];
	return tmp;
}
void del(int val)
{
	int x = nxt(val,0),y = nxt(val,1);
	splay(x,0);
	splay(y,x);
	int z = ch[y][0];
	if(z)
	{
		if(cnt[z] > 1)
		{
			cnt[z]--;
			splay(z,0);
		}
		else 
		{
			ch[y][0] = 0;
			cnt[z] = 0;
			splay(y,0);
		}
	}
}
int kth(int k)
{
	int y = root,x;
	if(k > sz[root]) return 0;
	while(1)
	{
		x = ch[y][1];
		if(sz[x]+cnt[y] < k)
		{
			k -= sz[x]+cnt[y];
			y = ch[y][0];
		}
		else if(sz[x]>=k) y = x;
		else return v[y];
	}
}
int main()
{
	GET(n);
	GET(m);
	insert(0);
	insert(n+1);
	for(int i = 1; i <= n; i++) sat[i] = i,insert(1),amount[i] = 1;
	int a,b,c;
	for(int i = 1; i <= m; i++)
	{
		GET(op);
		if(op)
		{
			GET(a);
			printf("%d\n",kth(a+1));
		}
		else
		{
			GET(a),GET(b);
			a = find(a);
			b = find(b);
			if(a == b) continue;
			del(amount[a]);
			del(amount[b]);
			c = amount[a]+amount[b];
			sat[b] = a;
			amount[a] = c;
			amount[b] = c;
			insert(c);
		}
	}
}


版权声明:本文的版权归作者和CSDN博客所有,未经作者同意严禁转载,否则将追究其法律责任!

poj 2985 并查集+线段树 线段树求第k大数 The k-th Largest Group

题意:        有一群猫,现在给它们编号,然后组队,0 1 2 代表 1 号和 2 号的队伍合并。 1 4 询问第 4 大的队伍 Size 是多大。 解:(贴的,他写的好。表示学习)   ...

poj 2985 The k-th Largest Group 求第K大数 Treap, Binary Index Tree, Segment Tree

题目链接:点击打开链接 题意:有两种操作,合并集合,查询第K大集合的元素个数。(总操作次数为2*10^5) Treap模板(静态数组) #include #include #include...
  • yew1eb
  • yew1eb
  • 2014年05月23日 09:44
  • 1948

poj_2985 The k-th Largest Group 树状数组求第K大

前面说了树状数组的三个用途, 在

【树状数组求第k小+并查集】POJ 2985

http://poj.org/problem?id=2985 树状数组已经够神奇了,原来它还可以求第k小的元素........orz,位运算V5! #define N (1...
  • leolin_
  • leolin_
  • 2012年03月10日 10:01
  • 947

POJ 2985 Treap平衡树(求第k大的元素)

这题也可以用树状数组做,而且树状数组姿势更加优美,代码更加少,不过这个Treap树就是求第K大元素的专家……所以速度比较快! 这个也是从那本红书上拿的模板……自己找了资料百度了好久,才理解这个Tre...

poj 2985(并查集+线段树求K大数)

解题思路:这道题并查集很容易,合并时找到父节点就直接加上去就ok了。关键是如何求K大数,我一直在想用线段树怎么写,一开始想如果直接记录数的大小那肯定是没戏了,借鉴了一下别人的思路:区间[a,b]记录的...

Poj 2985 树状数组求第k大

链接:戳这里 The k-th Largest Group Time Limit: 2000MS Memory Limit: 131072K Description ...
  • libin66
  • libin66
  • 2016年03月26日 15:48
  • 156

The k-th Largest (并查集+线段树)

The k-th Largest Group Time Limit: 2000ms Memory Limit: 131072KB 64-bit integer IO format: %lld  ...
  • x_y_q_
  • x_y_q_
  • 2016年07月07日 15:57
  • 283

poj 2104 K-th Number (主席树学习第一弹)

题目链接:poj 2104题目大意:给出n个数,询问m次,每次询问在区间[l,r]里的第k大的树。题目分析: 其实是可以直接划分树搞的,但是为了学习主席树,写了一发,发现代码量更少更简洁。 首先将数字...

POJ 2104 K-th Number [主席树入门]【数据结构】

题目链接:http://poj.org/problem?id=2104 ———————————————————————————————————————————————— K-th Number ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:POJ2985 The k-th Largest Group(Splay)
举报原因:
原因补充:

(最多只允许输入30个字)