hdu 1512 Monkey King

并查集显然要用到

左偏树解决合并的问题

这题体现了数据结构的强大啊!

  
    
#include < stdio.h >
#include
< algorithm >
using namespace std;
const int MAXN = 100100 ;
int father[MAXN];
struct Monkey{
int l,r;
int dis;
int strong;
}LTree[MAXN];
int find( int x){
if (x != father[x])
father[x]
= find(father[x]);
return father[x];
}
int merge( int x, int y){ // 返回合并后的根
if ( x == 0 )
return y;
if ( y == 0 )
return x;
if ( LTree[x].strong < LTree[y].strong) // 大顶堆
swap(x,y); LTree[x].r = merge(LTree[x].r,y); // 递归合并右子树和Y
int l = LTree[x].l , r = LTree[x].r;
father[r]
= x; // 更新T右子树的根
if (LTree[l].dis < LTree[r].dis) // 维护堆性质
swap(LTree[x].l,LTree[x].r);
if (LTree[x].r == 0 ) // 如果没有右子树 则距离为0
LTree[x].dis = 0 ;
else
LTree[x].dis
= LTree[LTree[x].r].dis + 1 ;
return x;
}
int del( int x){ // 返回删除根以后左右子树的合并的根
int l,r;
l
= LTree[x].l;
r
= LTree[x].r;
father[l]
= l;
father[r]
= r;
LTree[x].l
= LTree[x].r = LTree[x].dis = 0 ;
return merge(l,r);
}
void solve( int x, int y){
LTree[x].strong
/= 2 ;
LTree[y].strong
/= 2 ; // 问每次PK以后,当前这个群体里力量最大的猴子的力量是多少。
int left,right;
left
= del(x);
right
= del(y);
left
= merge(left,x);
right
= merge(right,y);
left
= merge(left,right);
printf(
" %d\n " ,LTree[left].strong);
}
int main(){
int n,m,i,x,y;
while (scanf( " %d " , & n) == 1 ){
for (i = 1 ; i <= n; i ++ ){
scanf(
" %d " , < ree[i].strong);
LTree[i].l
= 0 ;
LTree[i].r
= 0 ;
LTree[i].dis
= 0 ;
father[i]
= i; // 起始已自己为父亲
}
scanf(
" %d " , & m);
for (i = 1 ; i <= m; i ++ ){
scanf(
" %d%d " , & x, & y);
int fx = find(x),fy = find(y);
if (fx == fy){
printf(
" -1\n " );
}
else {
solve(fx,fy);
}
}
}
return 0 ;
}

你可能感兴趣的:(HDU)