hdu 1512 Monkey King 左偏树

来源:互联网 发布:mac地址修改器win8.1 编辑:程序博客网 时间:2024/04/30 14:05

题意:有n个猴子,一开始每个猴子只认识自己。每个猴子有一个力量值,力量值越大表示这个猴子打架越厉害。如果2个猴子不认识,他们就会找他们认识的猴子中力量最大的出来单挑,单挑不论输赢,单挑的2个猴子力量值减半,这2拨猴子就都认识了,不打不相识嘛。现在给m组询问,如果2只猴子相互认识,输出-1,否则他们各自找自己认识的最牛叉的猴子单挑,求挑完后这拨猴子力量最大值。


分析:第一道左偏树的题。

左偏树的性质:
1.【堆性质】:节点的关键字大等于其儿子节点的关键字
2.【左偏性质】:定义节点到最近的叶节点的距离为节点距离,任意节点的左儿子的距离大于右儿子的距离
左偏树在实现插入操作时总是从右侧插入,也就是总是让短的一侧生长,如果右侧长于左侧,那么交换左右侧,继续从右侧生长

代码:
#include<iostream>#include<cstdio>#include<cstdlib>#define inf 0x7fffffff#define N 100005using namespace std;int n,m,v[N],l[N],r[N],fa[N],d[N];int find(int x){if (fa[x]==x) return x;fa[x]=find(fa[x]);return fa[x];}int merge(int x,int y){if (!x) return y;if (!y) return x;if (v[x]<v[y]) swap(x,y);r[x]=merge(r[x],y);fa[r[x]]=x;if (d[l[x]]<d[r[x]]) swap(l[x],r[x]);d[x]=d[r[x]]+1;return x;}int pop(int x){int p=l[x],q=r[x];fa[p]=p;fa[q]=q;l[x]=r[x]=d[x]=0;return merge(p,q);}int main(){while (scanf("%d",&n)!=EOF){for (int i=1;i<=n;i++)scanf("%d",&v[i]);for (int i=1;i<=n;i++){fa[i]=i;l[i]=r[i]=d[i]=0;}d[0]=-1;scanf("%d",&m);while (m--){int x,y;scanf("%d%d",&x,&y);int p=find(x),q=find(y);if (p==q) printf("%d\n",-1);else{int ra=pop(p);v[p]/=2;ra=merge(ra,p);int rb=pop(q);v[q]/=2;rb=merge(rb,q);printf("%d\n",v[merge(ra,rb)]);}}}}


0 0
原创粉丝点击