【HDU1512】Monkey King-左偏树+并查集(左偏树入门题)
来源:互联网 发布:已知矩阵的秩求未知数 编辑:程序博客网 时间:2024/06/06 17:40
测试地址:Monkey King
题目大意:有N(N≤100000)只猴子,标号为1~N,每只猴子有一个强壮值,一开始他们互相之间都不认识,但猴子避免不了争吵,它们之间会进行M(M≤100000)次争吵,每次争吵都是标号为a和b的两只互不认识的猴子相互争吵,争吵过后,他们就会分别去找他们所认识的最强壮(强壮值最大)的猴子来决斗,决斗过后决斗的两只猴子的强壮值减半(向下取整),但打斗过后两边的猴子就都会互相认识,互相认识的猴子之间就不会再进行争吵了,你的任务就是对于每次争吵,如果不发生争吵(即两方认识)输出-1,否则输出决斗后两方猴子中最强壮猴子的强壮值。
做法:初观察这一题,维护互相认识的关系可以用并查集O(N)解决,维护最大的强壮值似乎可以用堆来解决,但是两方猴子互相认识之后,两个堆之间需要合并,如果将一个堆中的元素一个一个插入另一个堆中,复杂度是O(N^2)的,不能接受,这时候就要引出可并堆这个数据结构了,而左偏树则是可并堆的一种实现方法,关于左偏树的教程网上很多这里就不讲了。于是这里我们维护很多个大根堆,每次决斗,删除两个堆的根节点,将它们的强壮值减半,然后再合并回原来的堆中,再将两个堆合并,输出根节点的强壮值即可。并查集可以在合并和删除的过程中一并维护。
以下是本人代码:
#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;int n,m,fa[100010];struct leftisttree{ int lc,rc,key,dis;}nd[100010];int find(int x) //并查集中的查找{ int r=x,i=x,j; while(fa[r]!=r) r=fa[r]; while(i!=r) j=fa[i],fa[i]=r,i=j; return r;}int merge(int x,int y) //合并堆并返回合并后堆的根{ if (!x) return y; if (!y) return x; if (nd[x].key<nd[y].key) swap(x,y); nd[x].rc=merge(nd[x].rc,y); int l=nd[x].lc,r=nd[x].rc; fa[r]=x; if (nd[l].dis<nd[r].dis) swap(nd[x].lc,nd[x].rc); nd[x].dis=nd[nd[x].rc].dis+1; return x;}int del(int x) //删除一个堆的根节点并返回左右子树合并后的根{ int l,r; l=nd[x].lc,r=nd[x].rc; fa[l]=l,fa[r]=r; nd[x].lc=nd[x].rc=nd[x].dis=0; return merge(l,r);}void solve(int x,int y) //求解决斗后最大的强壮值{ int l,r; nd[x].key/=2;nd[y].key/=2; l=del(x),r=del(y); l=merge(l,x),r=merge(r,y); l=merge(l,r); printf("%d\n",nd[l].key);}int main(){ while(scanf("%d",&n)!=EOF) { nd[0].lc=nd[0].rc=0;nd[0].dis=-1; for(int i=1;i<=n;i++) { scanf("%d",&nd[i].key); nd[i].lc=nd[i].rc=nd[i].dis=0; fa[i]=i; } scanf("%d",&m); for(int i=1,a,b;i<=m;i++){ scanf("%d%d",&a,&b); if (find(a)==find(b)) {printf("-1\n");continue;} solve(find(a),find(b));} } return 0;}
0 0
- 【左偏树+并查集】Monkey King HDU1512
- hdu1512-Monkey King- 左偏树+并查集
- 左偏树+并查集 hdu1512 Monkey King
- HDU1512 Monkey King【并查集+左偏树】
- 【HDU1512】Monkey King-左偏树+并查集(左偏树入门题)
- hdu1512 Monkey King【左偏堆、并查集】
- hdu1512:Monkey King(左偏树)
- hdu1512 & zoj2334Monkey King(左偏树 + 并查集)
- hdu1512 & zoj2334Monkey King(左偏树 + 并查集)
- hdu1512 & zoj2334Monkey King(左偏树 + 并查集)
- hdu1512 monkey king 左偏树
- HDU1512 Monkey King 左偏树
- ZOJ2334 HDU1512 Monkey King,左偏树
- 【HDU1512】【左偏树】Monkey King 题解
- [HDU1512]Monkey King(可并堆)
- ZOJ2334 Monkey King 左偏树+并查集
- hdu1512 & zoj2334Monkey King (左偏树 + 并查集(非优化的朴素并查集))
- HDU1512 Monkey King 解题报告【数据结构】【可并堆】【并查集】
- 数据化运营
- Android四大组件之Activity,Activity生命周期
- PAT1006
- HDU 5308 I Wanna Become A 24-Point Master
- QTP 正则表达式 学习
- 【HDU1512】Monkey King-左偏树+并查集(左偏树入门题)
- 【LeetCode】485. Max Consecutive Ones
- A Java RunTime Environment (JRE) or Java Development Kit (JDK) must be available in order
- topology中的配置文件和配置类
- java基础-------永远分不清的位运算符 与(&)、非(~)、或(|)、异或(^)
- Eclipse常用快捷键
- Java学习第十五天之Collection、Iterator、List
- jetty9安装配置
- 利用SELECT INTO创建临时表