HDU 1512 Monkey King 可并堆,左偏树
2017-02-03 14:22
435 查看
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1512
题意: 有n个猴子,一开始每个猴子只认识自己。每个猴子有一个力量值,力量值越大表示这个猴子打架越厉害。如果2个猴子不认识,他们就会找他们认识的猴子中力量最大的出来单挑,单挑不论输赢,单挑的2个猴子力量值减半,这2拨猴子就都认识了,不打不相识嘛。现在给m组询问,如果2只猴子相互认识,输出-1,否则他们各自找自己认识的最牛叉的猴子单挑,求挑完后这拨猴子力量最大值。
解题方法:首先很明显这题涉及到集合并的操作,要用到并查集。其次要找到某一拨猴子中力量最大值,找最大值最快的应该是堆。2拨猴子要快速合并而又不失堆的特性,想来想去左偏树比较合适。下面来说说左偏树:
然后左偏树有几个很重要的性质如下:
[性质1] 节点的键值小于或等于它的左右子节点的键值。
[性质2] 节点的左子节点的距离不小于右子节点的距离。
[性质3] 节点的左子节点右子节点也是一颗左偏树。
左偏树支持,插入,删除,去最小节点,以及最重要的合并操作,并且保证这些操作的复杂度为严格的log(n)。
下面给出合并操作的核心代码:
然后给出本题的完整代码,第一次写可并堆,代码是参考了别人写的。
题意: 有n个猴子,一开始每个猴子只认识自己。每个猴子有一个力量值,力量值越大表示这个猴子打架越厉害。如果2个猴子不认识,他们就会找他们认识的猴子中力量最大的出来单挑,单挑不论输赢,单挑的2个猴子力量值减半,这2拨猴子就都认识了,不打不相识嘛。现在给m组询问,如果2只猴子相互认识,输出-1,否则他们各自找自己认识的最牛叉的猴子单挑,求挑完后这拨猴子力量最大值。
解题方法:首先很明显这题涉及到集合并的操作,要用到并查集。其次要找到某一拨猴子中力量最大值,找最大值最快的应该是堆。2拨猴子要快速合并而又不失堆的特性,想来想去左偏树比较合适。下面来说说左偏树:
然后左偏树有几个很重要的性质如下:
[性质1] 节点的键值小于或等于它的左右子节点的键值。
[性质2] 节点的左子节点的距离不小于右子节点的距离。
[性质3] 节点的左子节点右子节点也是一颗左偏树。
左偏树支持,插入,删除,去最小节点,以及最重要的合并操作,并且保证这些操作的复杂度为严格的log(n)。
下面给出合并操作的核心代码:
int merge(int a, int b) //合并 { if(a == 0) return b; if(b == 0) return a; if(heap[a].v < heap[b].v) swap(a, b); heap[a].r = merge(heap[a].r, b); heap[heap[a].r].f = a; if(heap[heap[a].l].dis < heap[heap[a].r].dis) swap(heap[a].l, heap[a].r); if(heap[a].r == 0) heap[a].dis = 0; else heap[a].dis = heap[heap[a].r].dis + 1; return a; }
然后给出本题的完整代码,第一次写可并堆,代码是参考了别人写的。
//hdoj 1512 可并堆
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100005;
struct tree{int l, r, v, dis, f;}heap[maxn]; //左儿子,右儿子,权值, 距离,父亲节点
int merge(int a, int b) //合并 { if(a == 0) return b; if(b == 0) return a; if(heap[a].v < heap[b].v) swap(a, b); heap[a].r = merge(heap[a].r, b); heap[heap[a].r].f = a; if(heap[heap[a].l].dis < heap[heap[a].r].dis) swap(heap[a].l, heap[a].r); if(heap[a].r == 0) heap[a].dis = 0; else heap[a].dis = heap[heap[a].r].dis + 1; return a; }
int pop(int a){ //删除
int l = heap[a].l, r = heap[a].r;
heap[l].f = l, heap[r].f = r;
heap[a].l = heap[a].r = heap[a].dis = 0;
return merge(l, r);
}
int find(int a){ //查找
return heap[a].f == a ? a : find(heap[a].f);
}
int main(){
int n, m;
while(scanf("%d", &n) != EOF)
{
for(int i = 1; i <= n; i++){
scanf("%d", &heap[i].v);
heap[i].l = heap[i].r = heap[i].dis = 0;
heap[i].f = i;
}
scanf("%d", &m);
for(int i = 1; i <= m; i++){
int a, b, fa, fb;
scanf("%d%d", &a, &b);
fa = find(a), fb = find(b);
if(fa == fb){
printf("-1\n");
}
else{
heap[fa].v /= 2;
int u = pop(fa);
u = merge(u, fa);
heap[fb].v /= 2;
int v = pop(fb);
v = merge(v, fb);
printf("%d\n", heap[merge(u, v)].v);
}
}
}
return 0;
}
相关文章推荐
- 【HDU】1512 Monkey King 左偏树
- Hdu 1512 Monkey King 左偏树 解题报告
- 【左偏树】HDU1512-Monkey King
- HDU 1512 Monkey King 左偏树 + 并查集
- HDU 1512 Monkey King(左偏树)
- hdu 1512 Monkey King 左偏树
- hdu-1512 Monkey King [并查集+左偏树]
- hdu 1512 Monkey King (左偏树可并堆 并查集)
- HDU 1512 Monkey King(左偏树)
- HDU 1512 Monkey King 左偏树
- HDU 1512 Monkey King(左偏树模板题)
- hdu 1512 Monkey King (左偏树 可并堆)
- HDU 1512 Monkey King ——左偏树
- HDU 1512 HDOJ 1512 Monkey King ( 左偏树 ) ACM 1512 IN HDU
- HDU1512 Monkey King【并查集+左偏树】
- HDU 1512 Monkey King 并查集+左偏树
- hdu 1512 Monkey King 左偏树(可并堆)
- HDU 1512 Monkey King(左偏树)
- 数据结构(左偏树):HDU 1512 Monkey King
- ZOJ 2334 HDU 1512 Monkey King