[bzoj1455] Roman game_left-biased tree_union search

Roman Games bzoj-1455

    The main idea of ​​the title: give you n people, 2 operations, m operations: 1. Delete the minimum value of the set where the soldier i is located 2. Merge the groups where the two soldiers i and j are located

    英释:$1\le n\le 10^6$,$1\le m \le 10^5$。

      Idea: Another GXZlegend lecture, left-biased trees in the parallel heap. Learn about:

        A binary tree with heap properties satisfies that in any node x, dis[lson[x]]>=dis[rson[x]], where dis represents the longest number of steps the current node has taken to its right son. Merging is recursive merging. We recursively process the merge of left-biased trees with one or two nodes as root nodes. Obviously, the subtree of the left-biased tree is still a left-biased tree. We directly attach a subtree to the son of another subtree, and the root node of the two subtrees (the default large root heap) can be regarded as the combined root node.

        Attach the merge code...  

void merge(int x,int y)
{
	if(!x) return y;
	if(!y) return x;
	if(val[x]<val[y]) swap(x,y);
	rson[x]=merge(rson[x],y);
	if(dis[rson[x]]>dis[lson[x]]) swap(rson[x],lson[x]);
	dis [x] = dis [rson [x]] + 1;
	return x;
}

      As for this question, we can use and check to maintain which team each person is in.

    Finally, the ugly code is attached...  

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1000010
using namespace std;
int fa [N], rson [N], lson [N], dis [N], w [N];
bool k[N];
int find(int x)
{
	return fa[x]==x?x:(fa[x]=find(fa[x]));
}
int merge(int x,int y)
{
	if(!x) return y;
	if(!y) return x;
	if(w[x]>w[y]) swap(x,y);
	rson[x]=merge(rson[x],y);
	if(dis[rson[x]]>dis[lson[x]])
	{
		swap(lson[x],rson[x]);
	}
	dis [x] = dis [rson [x]] + 1;
	return x;
}
inline int Kill(int x)
{
	if(k[x]) return 0;
	x=find(x);
	int t=merge(lson[x],rson[x]);
	fa [x] = t;
	fa [t] = t;
	k[x]=true;
	return w[x];
}
intmain()
{
	int n,m;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&w[i]);
	}
	for(int i=1;i<=n;i++)
	{
		fa [i] = i;
	}
	char s[3];
	scanf("%d",&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%s",s+1);
		if(s[1]=='M')	
		{
			int x,y;
			scanf("%d%d",&x,&y);
			if(k[x]||k[y]) continue;
			x=find(x),y=find(y);
			if(x!=y) fa[x]=fa[y]=merge(x,y);
			// fa [y] = x;
		}
		else
		{
			int x;
			scanf("%d",&x);
			printf("%d\n",Kill(x));
		}
	}
	return 0;
}
/*
2
1 2
3
M 1 2
K 1
K 2
*/

    Summary: The errors are quite strange. The fa update is wrong when killing. The merge function pays attention to the exit condition when writing, and does not output x at all times.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324469455&siteId=291194637