猴子大王Monkey King 左偏树+并查集维护

Description

Once in a forest, there lived N aggressive monkeys. At the beginning, they each does things in its own way and none of them knows each other. But monkeys can‘t avoid quarrelling, and it only happens between two monkeys who does not know each other. And when it happens, both the two monkeys will invite the strongest friend of them, and duel. Of course, after the duel, the two monkeys and all of their friends knows each other, and the quarrel above will no longer happens between these monkeys even if they have ever conflicted.

Assume that every money has a strongness value, which will be reduced to only half of the original after a duel(that is, 10 will be reduced to 5 and 5 will be reduced to 2).

And we also assume that every monkey knows himself. That is, when he is the strongest one in all of his friends, he himself will go to duel.
在一个森林里住着N(N<=100000)只猴子。在一开始,他们是互不认识的。但是随着时间的推移,猴子们少不了争斗,但那只会发生在互不认识(认识具有传递性)的两只猴子之间。争斗时,两只猴子都会请出他认识的猴子里最强壮的一只(有可能是他自己)进行争斗。争斗后,这两只猴子就互相认识。

每个猴子有一个强壮值,但是被请出来的那两只猴子进行争斗后,他们的强壮值都会减半(例如10会减为5,5会减为2)。

现给出每个猴子的初始强壮值,给出M次争斗,如果争斗的两只猴子不认识,那么输出争斗后两只猴子的认识的猴子里最强壮的猴子的强壮值,否则输出 -1。

Input

There are several test cases, and each case consists of two parts.

First part: The first line contains an integer N(N<=100,000), which indicates the number of monkeys. And then N lines follows. There is one number on each line, indicating the strongness value of ith monkey(<=32768).

Second part: The first line contains an integer M(M<=100,000), which indicates there are M conflicts happened. And then M lines follows, each line of which contains two integers x and y, indicating that there is a conflict between the Xth monkey and Yth.
第一行, 一个整数N,表示猴子的数量 
接下来N行,表示猴子的强壮值(<=32767) 
接下来一行,一个整数M(M<=100,000)表示与M次争斗。 
接下来M行,每行两个整数X和Y,表示在编号X和编号Y的猴子间发生了争斗。

Output

For each of the conflict, output -1 if the two monkeys know each other, otherwise output the strongness value of the strongest monkey in all friends of them after the duel.
共M行,每行表示一次争斗的结果。如果争斗的两只猴子不认识,那么输出争斗后两只猴子的认识的猴子里最强壮的猴子的强壮值,否则输出 -1。

Sample Input

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

Sample Output

8
5
5
-1
10

Source

xinyue---ZOJ 2334

左偏树的模板,注意题目说的是打完架之后认识的最大值,不是那两只猴子!

code:

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 const int N=100003;
 5 struct node{
 6     int w,l,r,fa,d;
 7 }t[N];
 8 int find(int x){
 9     return x==t[x].fa?x:t[x].fa=find(t[x].fa);
10 }
11 int merge(int x,int y){//合并
12     if(!x||!y)return x+y;//有一个是空的树就直接返回另一个编号
13     if(t[x].w<t[y].w)swap(x,y);//由于维护的是大根堆所以左边比右边小要进行交换
14     t[x].r=merge(t[x].r,y);//右子树的根就是合并过后的编号
15     if(!t[x].l||t[t[x].l].d<t[t[x].r].d)swap(t[x].l,t[x].r);//如果左边根本就没有树或者是左边的路径长小于右边就要交换
16     t[x].d=t[t[x].l].d+t[t[x].r].d+1;//更新右子树路径的长度
17     return x;//返回新结合的根节点
18 }
19 int del(int x){
20     int root=merge(t[x].l,t[x].r);
21     t[x].l=t[x].r=0;
22     return root;
23 }
24 int main ()
25 {
26     int n;cin>>n;
27     for(int i=1;i<=n;i++){
28         scanf("%d",&t[i].w);
29         t[i].fa=i;
30     }
31     cin>>n;
32     while(n--){
33         int x,y;
34         scanf("%d%d",&x,&y);
35         x=find(x),y=find(y);//找出里面根,与维护并查集是一个道理
36         if(x==y){
37             printf("-1\n"); continue;
38         }
39         //printf("%d\n",max(t[x].w,t[y].w)/2);
40         int a=del(x),b=del(y);//删除这两个代表性的值
41         t[x].w>>=1, t[y].w>>=1;//这两个猴子打完架之后除以2
42         int root=merge(a,b);//链接a,b
43         root=merge(root,x); root=merge(root,y);//合并一下树
44         t[x].fa=t[y].fa=t[root].fa=root;//更新他们的根节点的值
45         printf("%d\n",t[root].w);
46     }
47     return 0;
48 }

over

原文地址:https://www.cnblogs.com/saionjisekai/p/9715222.html

时间: 2024-08-18 15:50:11

猴子大王Monkey King 左偏树+并查集维护的相关文章

zoj 2334 Monkey King/左偏树+并查集

原题链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1389 大致题意:N只相互不认识的猴子(每只猴子有一个战斗力值) 两只不认识的猴子之间发生冲突,两只猴子会分别请出它们认识的最强壮的 猴子进行决斗.决斗之后这,两群猴子都相互认识了. 决斗的那两只猴子战斗力减半...有m组询问 输入a b表示猴子a和b发生了冲突,若a,b属于同一个集合输出-1 否则输出决斗之后这群猴子(已合并)中最强的战斗力值... 具体思路:用并查

模板 - 左偏树 + 并查集

这两个经常混在一起用的样子,封成同一个好了. #include<bits/stdc++.h> using namespace std; typedef long long ll; int solve(); int main() { #ifdef Yinku freopen("Yinku.in","r",stdin); #endif // Yinku solve(); } int n,m; const int MAXN=100005; int tot,v[

hdu 1512 Monkey King 左偏树

题目链接:HDU - 1512 Once in a forest, there lived N aggressive monkeys. At the beginning, they each does things in its own way and none of them knows each other. But monkeys can't avoid quarrelling, and it only happens between two monkeys who does not kn

[BZOJ1455]罗马游戏-斜堆/左偏树-并查集(+数据生成器)

Problem 遗产 题目大意 罗马皇帝很喜欢玩杀人游戏. 他的军队里面有n个人,每个人都是一个独立的团.最近举行了一次平面几何测试,每个人都得到了一个分数. 皇帝很喜欢平面几何,他对那些得分很低的人嗤之以鼻.他决定玩这样一个游戏. 它可以发两种命令: 1. Merger(i, j).把i所在的团和j所在的团合并成一个团.如果i, j有一个人是死人,那么就忽略该命令. 2. Kill(i).把i所在的团里面得分最低的人杀死.如果i这个人已经死了,这条命令就忽略. 皇帝希望他每发布一条kill命令

[BZOJ 1455]罗马游戏(左偏树+并查集)

Description 罗马皇帝很喜欢玩杀人游戏. 他的军队里面有n个人,每个人都是一个独立的团.最近举行了一次平面几何测试,每个人都得到了一个分数. 皇帝很喜欢平面几何,他对那些得分很低的人嗤之以鼻.他决定玩这样一个游戏. 它可以发两种命令: 1. Merger(i, j).把i所在的团和j所在的团合并成一个团.如果i, j有一个人是死人,那么就忽略该命令. 2. Kill(i).把i所在的团里面得分最低的人杀死.如果i这个人已经死了,这条命令就忽略. 皇帝希望他每发布一条kill命令,下面的

【BZOJ 1455】 1455: 罗马游戏 (可并堆-左偏树+并查集)

1455: 罗马游戏 Description 罗马皇帝很喜欢玩杀人游戏. 他的军队里面有n个人,每个人都是一个独立的团.最近举行了一次平面几何测试,每个人都得到了一个分数. 皇帝很喜欢平面几何,他对那些得分很低的人嗤之以鼻.他决定玩这样一个游戏. 它可以发两种命令: 1. Merger(i, j).把i所在的团和j所在的团合并成一个团.如果i, j有一个人是死人,那么就忽略该命令. 2. Kill(i).把i所在的团里面得分最低的人杀死.如果i这个人已经死了,这条命令就忽略. 皇帝希望他每发布一

bzoj 1455: 罗马游戏 左偏树+并查集

1455: 罗马游戏 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 668  Solved: 247[Submit][Status] Description 罗马皇帝很喜欢玩杀人游戏. 他的军队里面有n个人,每个人都是一个独立的团.最近举行了一次平面几何测试,每个人都得到了一个分数. 皇帝很喜欢平面几何,他对那些得分很低的人嗤之以鼻.他决定玩这样一个游戏. 它可以发两种命令: 1. Merger(i, j).把i所在的团和j所在的团合并成一个团.如果

HDU 1512 Monkey King ——左偏树

[题目分析] 也是堆+并查集. 比起BZOJ 1455 来说,只是合并的方式麻烦了一点. WA了一天才看到是多组数据. 盲人OI (- ̄▽ ̄)- Best OI. 代码自带大常数,比启发式合并都慢 [代码] #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <set> #include <map> #include <

HDU ACM 1512 Monkey King-&gt;左偏树+并查集

题意:一开始有N只猴子,,每只都有一个力量值.,并且互不认识,后来 它们之间发生了M次斗争. 每次两次两只猴子a,b斗争是, a和 b都会从他们自己的朋友圈里拉出一个最强的朋友, 之后最强的这两只猴子打, 打完后两只猴子的力量值分别减半..并且 两只猴子的朋友圈的所有人都互相认识(也就是以后不会再打了).问题是对于每次斗争, 若a,b是朋友, 那么输出-1, 否则输出斗争后它们的朋友圈里最强猴子的力量值. 分析:要表示集合的合并查找操作就是并查集最好了:要维护每次的最大值,就可以使用大顶堆,但还