您的位置:首页 > 其它

hdu1512 & zoj2334Monkey King (左偏树 + 并查集(非优化的朴素并查集))

2015-07-28 21:30 405 查看
在一个森林里住着N(N<=10000)只猴子。

在一开始,他们是互不认识的。但是随着时间的推移,猴子们少不了争斗,但那只会发生在互不认识(认识具有传递性)的两群猴子之间(可能只有他们自己)。

争斗时,两群猴子都会请出他们里面最强壮的一只(有可能是他自己)进行争斗。

争斗后,这两群猴子就互相认识。

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

现给出每个猴子的初始强壮值,给出M次争斗,

如果争斗的两只猴子不认识,那么输出争斗后两只猴子的认识的猴子里最强壮的猴子的强壮值,否则输出-1。

hdu http://acm.hdu.edu.cn/showproblem.php?pid=1512

zoj http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2334

左偏树入门详见讲义,要先看看讲义理解理解左偏树的实现,下载链接

http://download.csdn.net/detail/hnust_taoshiqian/8941099

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#define MT(x,i) memset(x,i,sizeof(x))
using namespace std;
const int maxn=100000+10;
int tot,v[maxn],l[maxn],r[maxn],d[maxn],fa[maxn];
///value,left,right,dist(到最近外点的距离(外点:没有两个儿子的点))
int Merge(int x,int y){
if(x==y) return x;
if(!x) return y;
if(!y) return x;
if(v[x]<v[y]) swap(x,y);///保证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 Init(int x){
v[tot]=x;
l[tot]=r[tot]=d[tot]=0;
return tot++;
}
int Insert(int x,int y){///向编号为x的左偏数中插入权值为y的节点
return Merge(x,Init(y));
}
int Top(int x){
return v[x];
}
int Pop(int x){
fa[l[x]]=l[x]; fa[r[x]]=r[x];
return Merge(l[x],r[x]);
}
int Find(int x){
while(fa[x]!=x) x=fa[x];
return x;
}
void init0(){
MT(l,0);MT(r,0);MT(d,0);
tot=1;
}
int main()
{
int n,m,x,y;
while(~scanf("%d",&n)){
init0();
for(int i=1;i<=n;i++){
scanf("%d",&v[i]);
fa[i]=i;
}
for(scanf("%d",&m);m--;){
scanf("%d%d",&x,&y);
int fx=Find(x),fy=Find(y);
if(fx==fy){puts("-1");continue;}///认识

int rt=Pop(fx);///x树的根,也是最大值
v[fx]/=2;l[fx]=r[fx]=d[fx]=0;
fx=Merge(rt,fx);
rt=Pop(fy);///y树的根,也是最大值
v[fy]/=2;l[fy]=r[fy]=d[fy]=0;
fy=Merge(rt,fy);

if(v[fx]>v[fy]) printf("%d\n",v[fx]);
else printf("%d\n",v[fy]);
Merge(fx,fy);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: