Monkey King【大根堆】
题目链接
有N只孤独的猴子,然后他们会打M次架,每次打架的两只猴子战斗力减半,并且会成为朋友,朋友的朋友也是朋友,问的是朋友中战力最大的猴子是有多少战力?
于是,考虑维护这样的一个大根堆,每次将小的大根堆推给大的,相当于是启发式合并的操作,复杂度。
或者,我们可以直接进行维护,我们维护一个二叉树的“深度”,然后尽量保证深度平衡,也就是使得整棵二叉树的深度尽可能小,所以,我们定义一个dist,表示它和它的子树中的dist最小的值+1,但是这样的维护最后可能退化会形成一条链,不妥,不如我们让左子树的dist大于右子树的dist,然后这样子推下去,最后让根节点的dist等于右子树的dist+1即可。
于是,每次就是合并两棵子树就可以了,合并的时候复杂度为级别,然后删除的时候,实际上就是对左右两棵子树合并,然后插入的时候实际上就是对一个堆大小为1的点的合并了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define pii pair<int, int>
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 1e5 + 7;
int N, M;
struct node
{int val, d, c[2], fa;node(int a=0, int b=0, int c1=0, int c2=0, int f=0):val(a), d(b), c{c1, c2}, fa(f) {}
} t[maxN];
int fid(int x) { return x == t[x].fa ? x : t[x].fa = fid(t[x].fa); }
int Merge(int x, int y)
{if(!x || !y) return x | y;if(t[x].val < t[y].val) swap(x, y);t[x].c[1] = Merge(t[x].c[1], y);t[t[x].c[1]].fa = x;if(t[t[x].c[0]].d < t[t[x].c[1]].d) swap(t[x].c[0], t[x].c[1]);t[x].d = t[t[x].c[1]].d + 1;return x;
}
int pop(int x)
{t[t[x].c[0]].fa = t[x].c[0];t[t[x].c[1]].fa = t[x].c[1];t[x].val >>= 1;int y = Merge(t[x].c[0], t[x].c[1]);memset(t[x].c, 0, sizeof(t[x].c));return Merge(x, y);
}
int main()
{while(scanf("%d", &N) != EOF){for(int i=1; i<=N; i++){scanf("%d", &t[i].val);memset(t[i].c, 0, sizeof(t[i].c));t[i].fa = i; t[i].d = 0;}scanf("%d", &M);for(int i=1, x, y, fx, fy, ff; i<=M; i++){scanf("%d%d", &x, &y);fx = fid(x); fy = fid(y);if(fx == fy) { puts("-1"); continue; }if(t[fx].val < t[fy].val) swap(fx, fy);ff = Merge(pop(fx), pop(fy));printf("%d\n", t[ff].val);}}return 0;
}
Monkey King【大根堆】相关推荐
- LuoguP1456 - Monkey King| 左倾堆 | 左偏树
洛谷P1456 有n只猴子,每只猴子的战斗力为ai.m次操作,每次操作过后,猴子认识的猴子中(包括自己)战斗力最大的战斗力减半.操作后,两只猴子从不认识变为认识.输出打完架之后猴子认识的猴子中的最大战 ...
- Monkey King(左偏树 可并堆)
我们知道如果要我们给一个序列排序,按照某种大小顺序关系,我们很容易想到优先队列,的确很方便,但是优先队列也有解决不了的问题,当题目要求你把两个优先队列合并的时候,这就实现不了了 优先队列只有插入 删除 ...
- Monkey King(猴王)——可并堆走起
猴王 时间限制: 1 Sec 内存限制: 128 MB题目描述很久很久以前,在一个广阔的森林里,住着n只好斗的猴子.起初,它们各干各的,互相之间也不了解.但是这并不能避免猴子们之间的争吵,当然,这只存 ...
- 有趣的排序算法——Monkey King排序 详细介绍
<关于某位小蒟蒻在机房划水没事干于是瞎搞的那档事> 前言 排序算法在题目中经常需要用到,在程序中,我们一般打的是快排,归并,堆排等高效率排序,更有甚者会直接用sort排序,而今天,我要介绍 ...
- 洛谷1456 Monkey King
题目:Monkey King 思路:左偏树.对于每次操作 x y ,先让x,y等于各自朋友中最大的那个,即x=find(x),y=find(y),然后再分别把x,y删除,修改权值后重新加入堆中. 代码 ...
- 【HDU 1512】Monkey King
[题目] 传送门 Problem Description Once in a forest, there lived N aggressive monkeys. At the beginning, t ...
- zoj 2334 Monkey King
左偏树加并查集 一开始,对于每一个monkey建立一个单节点的左偏树. 对于每一次duel.,将对应的两只monkey的左偏树根节点的值减半,即最强壮的两只monkey强壮值减半,更新维护两个对应的左 ...
- 大根堆的删除c语言,二叉堆(一)之 C语言详解
本文介绍二叉堆,二叉堆就是通常我们所说的数据结构"堆"中的一种.和以往一样,本文会先对二叉堆的理论知识进行简单介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现: ...
- 【数据结构】堆,大根堆,小根堆,优先队列 详解
目录 堆 1.堆的数组实现 2.小根堆 3.大根堆 4.优先队列 例题 1.SP348 EXPEDI - Expedition(有趣的贪心思路,优先队列) 2.合并果子 堆 要了解堆之前,请先了解树, ...
最新文章
- VIM — vim-go
- 思科交换机和路由器的远程配置
- invalid new-expression of abstract class type 'CurveFittingEdge'
- why fioriSandboxConfig.json is loaded twice
- opengl 如何加阴影_OpenGL + Qt: 3 - 旋转动画和键盘操纵
- 一篇小文带你走进RabbitMQ的世界
- 芯片测试探针卡_测试接口业者先受惠苹果A14 GPU双雄4Q再加Socket、探针卡急单
- constellio——基于solr的开源搜索引擎系统源码研究(五)
- python开发图片_python实现简单的图片隐写术
- Bailian2696 计算表达式的值【入门】
- 拓端tecdat|R语言确定聚类的最佳簇数:3种聚类优化方法
- FANUC NC GUIDE PRO 17.1虚拟机(XP系统)
- 分析学中的若干空间:
- intuitionistic fuzzy set 运算规则python实现
- BK7256,上海博通-音视频Wi-Fi6combo-soc,内置Flash,RGB屏驱\720P
- 加入NLP交流群和求职群
- 英文写作中单词的用法
- 别人的面经(算法方向)
- BLE广播包4种类型
- Android — jimu Mirror