LUOGU p1456 MK

题意翻译

题目描述

曾经在一个森林中居住着 N 只好斗的猴子。在最初他们我行我素,互不认识。但是猴子们不能避免争吵,且两只猴子只会在不认识对方时发生争吵,当争吵发生时,双方会邀请它们各自最强壮的朋友并发起决斗(决斗的为各自最强壮的朋友)。当然,在决斗之后两只猴子和他们各自的伙伴都认识对方了(成为朋友),虽然他们曾经有过冲突,但是他们之间绝不会再发生争吵了。

假设每只猴子有一个强壮值,强壮值将在一场决斗后减少为原先的一半(例如 10 会减少到 5,而 5 会减少到 2,即向下取整)。

我们也假设每只猴子都认识它自己(是自己的朋友)。即当他是他朋友中最强壮的,他自己就会去决斗。

输入格式

有多组数据,每一组数据有两部分。

第一部分:第一行包含一个整数 N 表示猴子的数量。后为 N 行,每行一个数字为第 i 只猴子的强壮值 \(s_{i}\)

第二部分:第一行包含一个整数 M 表示发生了 M 次冲突。后为 M 行,每行两个整数 x 和 y,表示第 x 只猴子和第 y 只猴子之间发生了冲突。

输出格式

对于每次冲突,如果两只猴子认识对方,输出 -1,否则输出决斗后他们朋友中最强壮的猴子的强壮值。

说明/提示

\(N,M\leq 100000,s_{i}\leq 32768\)

输入输出样例

输入

5
20
16
10
10
4
5
2 3
3 4
3 5
4 5
1 5

输出

8
5
5
-1
10

说明/提示

题目可能有多组数据

左偏树模板题目
左偏树是一种可并堆,它除了可以实现普通堆的插入、删除、取堆顶的操作外,还能够在log时间内实现两个堆的合并。
注意:左偏树的合并操作是递归实现,不能同时实现并查操作。需要单独加入操作。
int e=merge(c,d);
fa[c]=fa[d]=e;


#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n,m;
int l[maxn],r[maxn],fa[maxn],dis[maxn],w[maxn];
int merge(int a,int b)
{
	if(!a||!b)return a+b;
	if(w[a]<w[b])swap(a,b);
	r[a]=merge(r[a],b);
	if(dis[r[a]]>dis[l[a]])swap(r[a],l[a]);
	dis[a]=dis[r[a]]+1;
	return a;
}
int find(int x)
{
	return fa[x]==x?x:find(fa[x]);
}
int del(int x)
{
	w[x]>>=1;
	int y=merge(l[x],r[x]);
	l[x]=r[x]=dis[x]=0;
	int z=merge(x,y);
	fa[x]=fa[y]=z;
	return z;
}
int main()
{
	while(scanf("%d",&n)==1)
	{
		for(int i=1;i<=n;++i)
		{
			scanf("%d",w+i);
			l[i]=r[i]=dis[i]=0;
			fa[i]=i;
		}
		scanf("%d",&m);
		for(int a,b,i=1;i<=m;++i)
		{
			scanf("%d%d",&a,&b);
			a=find(a);
			b=find(b);
			if(a==b)
			{
				printf("-1\n");
				continue;
			}
			int c=del(a);
			int d=del(b);
			int e=merge(c,d);
			fa[c]=fa[d]=e;
			printf("%d\n",w[e]);
		}
	}
	return 0;
}

posted on 2022-07-25 09:19  gryzy  阅读(52)  评论(0编辑  收藏  举报

导航