zoukankan      html  css  js  c++  java
  • [poj-2985]The k-th Largest Group_Treap+并查集

    The k-th Largest Group poj-2985

        题目大意:给你n只猫,有两种操作:1.将两只猫所在的小组合并。2.查询小组数第k大的小组的猫数。

        注释:1<=n,m<=200,000.

          想法:开始的想法就是用Treap合并,用Treap删除。然后发现Treap合并实在是...太tm gay了。没办法,用并查集吧。想法就出现了,我们用并查集合并,用Treap查询k大值。考虑怎么实现:因为我们想用Treap查询k大值,所以我们Treap中维护的一定是集合中猫的个数。并查集的合并呢?我们可以只在并查集森林的根节点处维护每一颗并查集的节点数。用并查集直接合并就行,我们考虑如何进行Treap中的修改?我们可以先把两只猫的集合先删掉,然后在加入一个两只猫集合总数的节点即可。那么,这题就切了吗对不对... ...

        最后,附上丑陋的代码... ...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int tot,root;
    int number[400010];
    int fa[400010];
    struct Node
    {
    	int lson,rson;
    	int size,num;
    	int val,rnd;
    }a[400010];
    inline void update(int k)
    {
    	a[k].size=a[a[k].lson].size+a[a[k].rson].size+a[k].num;
    }
    void lturn(int &k)
    {
    	int t=a[k].rson;
    	a[k].rson=a[t].lson;
    	a[t].lson=k;
    	update(k);update(t);k=t;
    }
    void rturn(int &k)
    {
    	int t=a[k].lson;
    	a[k].lson=a[t].rson;
    	a[t].rson=k;
    	update(k);update(t);k=t;
    }
    void insert(int &k,int temp)
    {
    	if(!k)
    	{
    		k=++tot;
    		a[k].num=a[k].size=1;
    		a[k].val=temp;
    		a[k].rnd=rand();
    		return;
    	}
    	a[k].size++;
    	if(temp==a[k].val) a[k].num++;
    	else if(temp<a[k].val)
    	{
    		insert(a[k].lson,temp);update(k);
    		if(a[a[k].lson].rnd<a[k].rnd) rturn(k);
    	}
    	else
    	{
    		insert(a[k].rson,temp);update(k);
    		if(a[a[k].rson].rnd<a[k].rnd) lturn(k);
    	}
    }
    void del(int &k,int temp)
    {
    	if(!k) return;
    	if(temp==a[k].val)
    	{
    		if(a[k].num>1)
    		{
    			a[k].num--;
    			a[k].size--;
    		}
    		else if(a[k].lson==0||a[k].rson==0)
    		{
    			k=a[k].lson+a[k].rson;
    		}
    		else if(a[a[k].lson].rnd<a[a[k].rson].rnd)
    		{
    			rturn(k);
    			del(k,temp);
    		}
    		else
    		{
    			lturn(k);
    			del(k,temp);
    		}
    	}
    	else if(temp<a[k].val)
    	{
    		a[k].size--;
    		del(a[k].lson,temp);
    	}
    	else
    	{
    		a[k].size--;
    		del(a[k].rson,temp);
    	}
    }
    int ask_num(int k,int temp)
    {
    	if(k<=0||temp<=0) return 0;
    	if(temp<=a[a[k].lson].size) return ask_num(a[k].lson,temp);
    	else if(temp>a[a[k].lson].size+a[k].num)
    	{
    		return ask_num(a[k].rson,temp-a[k].num-a[a[k].lson].size);
    	}
    	else return a[k].val;
    }
    int find(int x)
    {
    	return fa[x]==x?x:(fa[x]=find(fa[x]));
    }
    void merge(int x,int y)
    {
    	x=find(x);y=find(y);
    	fa[x]=y;
    	number[y]+=number[x];
    }
    void original()
    {
    	memset(a,0,sizeof a);
    	root=0;
    	tot=0;
    }
    int main()
    {
    	int n,m;
    	while(~scanf("%d%d",&n,&m))
    	{
    		original();
    		for(int i=1;i<=n;i++)
    		{
    			fa[i]=i;
    			number[i]=1;
    		}
    		root=1;
    		tot=1;
    		a[1].val=1;
    		a[1].size=a[1].num=n;
    		a[1].rnd=rand();
    		int flag;
    		int x,y;
    		for(int i=1;i<=m;i++)
    		{
    			scanf("%d",&flag);
    			if(!flag)
    			{
    				scanf("%d%d",&x,&y);
    				if(find(x)==find(y)) continue;
    				del(root,number[find(x)]);
    				del(root,number[find(y)]);
    				insert(root,number[find(x)]+number[find(y)]);
    				merge(x,y);
    			}
    			else
    			{
    				scanf("%d",&x);
    				printf("%d
    ",ask_num(root,a[root].size-x+1));
    			}
    		}
    	}
    }
    

         小结:我的并查集最后写错了,导致调了5h... ...

  • 相关阅读:
    第一次软工作业
    项目复审&事后诸葛亮分析
    测试与发布
    团队项目scrum冲刺日志合集
    团队作业3
    团队作业2
    团队作业1-团队展示&选题
    结对项目, 四则运算
    个人项目作业
    自我介绍+软工五问
  • 原文地址:https://www.cnblogs.com/ShuraK/p/8491859.html
Copyright © 2011-2022 走看看