您的位置:首页 > 其它

[HDU1512] Monkey King

2017-08-03 10:54 106 查看

题意

N只好斗的猴子.开始,他们各自为政,互不相干.但是猴子们不能消除争吵,但这仅仅发生在两只互不认识的猴子之间.当争吵发生时,争吵的两只猴子都会求助他们各自最强壮的朋友,并且决斗.当然,决斗之后,两只猴子及他们所有的朋友都相互认识了,并且成为朋友,争吵将不会在他们之间发生.

假定每一只猴子有一个强壮值,在每次决斗之后变为原来的一半(例如,10将为变为5,5将会变为2).

假定每一只猴子认识他自己. 也就是当他发生争吵,并且自己是他的朋友中最强壮的,他将代表自己进行决斗.

对于每一次争吵,如果两只猴子认识,输出-1,否则输出一个数,表示决斗后朋友中最强壮猴子的强壮值.

题解

每次两个猴子争吵相当于两个点集的合并,每个点集都需要维护最大值,又要维护点之间的连通性。故用左偏树维护最大值与合并,并查集维护连通性。

代码

/// by ztx
/// blog.csdn.net/hzoi_ztx
#include <bits/stdc++.h>
#define Rep(i,l,r) for(i=(l);i<=(r);i++)
#define rep(i,l,r) for(i=(l);i< (r);i++)
#define Rev(i,r,l) for(i=(r);i>=(l);i--)
#define rev(i,r,l) for(i=(r);i> (l);i--)
#define Each(i,v)  for(i=v.begin();i!=v.end();i++)
typedef long long ll ;
typedef double lf ;
int CH , NEG ;
template <typename TP>inline void read(TP& ret) {
ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;
if (CH == '-') NEG = true , CH = getchar() ;
while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
if (NEG) ret = -ret ;
}

#define  kN  100010LL

struct lt {
lt *l, *r;
int w, d;
lt();
lt(int w);
}*null=new lt();
lt::lt() { l=r=null;w=d=0; }
lt::lt(int w): w(w) { l=r=null;d=0; }
lt* Init(int x) { return new lt(x); }
lt* Merge(lt*u,lt*v) {
if (u == null) return v;
if (v == null) return u;
if (u->w < v->w) std::swap(u,v);
u->r = Merge(u->r,v);
if (u->l->d < u->r->d) std::swap(u->l,u->r);
u->d = u->r->d+1;
return u;
}
void Insert(lt*&u,int x) { u = Merge(u,Init(x)); }
int Top(lt*u) { return u->w; }
void Pop(lt*&u) { lt*tmp = u; u = Merge(u->l,u->r); delete tmp; }
bool Empty(lt*u) { return u == null; }

int n, fa[kN] = {0};
lt*q[kN];

inline int GetAnc(int u) { return fa[u]?fa[u]=GetAnc(fa[u]):u; }

#define r(x)   read(x)
inline void work() {
int i, u, v, wu, wv;
Rep (i,1,n)
r(v), q[i] = Init(v), fa[i] = 0;
r(i);
while (i --> 0) {
r(u), r(v);
u = GetAnc(u), v = GetAnc(v);
if (u == v) { puts("-1"); continue; }
wu = Top(q[u]), Pop(q[u]), wu >>= 1, Insert(q[u],wu);
wv = Top(q[v]), Pop(q[v]), wv >>= 1, Insert(q[v],wv);
printf("%d\n", std::max(Top(q[u]),Top(q[v])));
fa[v] = u;
q[u] = Merge(q[u],q[v]);
}
}

int main() {
while (scanf("%d",&n)!=EOF)work();
END: getchar(), getchar();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: