题目:猴王 Monkey King
题目描述
很久很久以前,在一个广阔的森林里,住着n只好斗的猴子。起初,它们各干各的,互相之间也不了解。但是这并不能避免猴子们之间的争吵,当然,这只存在于两个陌生猴子之间。当两只猴子争论时,它们都会请自己最强壮的朋友来代表自己进行决斗。显然,决斗之后,这两只猴子以及它们的朋友就互相了解了,这些猴子之间将再也不会发生争论了,即使它们曾经发生过冲突。
假设每一只猴子都有一个强壮值,每次决斗后都会减少一半(比如10会变成5,5会变成2.5)。并且我们假设每只猴子都很了解自己。就是说,当它属于所有朋友中最强壮的一个时,它自己会站出来,走向决斗场。
输入
输入分为两部分。
第一部分,第一行有一个整数n(n<=100000),代表猴子总数。
接下来的n行,每行一个数表示每只猴子的强壮值(小于等于32768)。
第二部分,第一行有一个整数m(m<=100000),表示有m次冲突会发生。
接下来的m行,每行包含两个数x和y,代表第x个猴子和第y个猴子之间发生冲突。
输出
输出每次决斗后在它们所有朋友中的最大强壮值。数据保证所有猴子决斗前彼此不认识。
样例输入
5
20
16
10
10
4
4
2 3
3 4
3 5
1 5
样例输出
8
5
5
10
解析
首先,看到题目我们首先会想到,并查集和堆,因为我们每一次都要从一群猴子中找出最强壮的,暴力搜一遍显然不行,因此要用到堆,然后两只猴子打架后需要将两群猴子合并,因此要用到并查集,但是同时写这两种数据结构太麻烦,所以要借助一种既具有查找功能又具有合并功能的数据结构–左偏树。
下面简单讲一讲左偏树,首先定义几个概念,
1.外结点:左子树或右子数为空的结点即无左子树或右子树。
2.结点i的距离:结点i到后代最近的外结点的所经过的边数。
3.左偏性质:一棵左偏树中任意结点的左子结点距离大于右子节点距离。
上图![摘自百度百科](https://img-blog.csdn.net/20170704192928451?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzc0OTQyOTY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
图中外结点有18 20 19 24 15 30 28 11 21 16 42 50 33 26 27。
蓝色数字为该结点的距离。
由第二,三条概念得一个结点的距离一定是它右子结点(如果有)的距离+1,因为左子结点距离大于等于右子结点距离,结点距离又要求最近。
左偏树基本操作(大根为例):
1.合并操作(合并两棵左偏树):将两棵树中较大的根结点,作为合并后的树的根结点,将根较小的树与根较大的树的右子结点继续合并操作,直到无子结点。合并后如果不满足左偏树性质,即左子结点距离小于右子结点距离则维护,即交换指针。