左偏树加并查集
一开始,对于每一个monkey建立一个单节点的左偏树。
对于每一次duel.,将对应的两只monkey的左偏树根节点的值减半,即最强壮的两只monkey强壮值减半,更新维护两个对应的左偏树的大根堆性质,然后合并。
修改两只monkey对应的左偏树为新合并出来的大根堆左偏树。然后输出这个大根堆的根节点的值,所有朋友中的最强壮一个。
不知道为什么,一直SF....................
#include <iostream>
#include <cstdio>
#define MAXN 100100
using namespace std;
struct HBLT
{
int value;
int dist;
HBLT* lchild;
HBLT* rchild;
};
HBLT* parent[MAXN];
//合并操作
HBLT* merge(HBLT* A,HBLT* B)
{
if (A==0)
return B;
if (B==0)
return A;
HBLT *Z;
if (A->value<B->value){
Z = A;
A = B;
B = Z;
}
A->rchild = merge(A->rchild,B);
if (A->rchild==0) return A;
if (A->lchild==0||A->rchild->dist > A->lchild->dist){
Z = A->rchild;
A->rchild = A->lchild;
A->lchild = Z;
}
if (A->rchild!=0)
A->dist = A->rchild->dist +1;
else
A->dist = 0;
return A;
}
//维护大根堆性质
void update(HBLT * A)
{
if (A->lchild==0&&A->rchild==0) return;
HBLT *Z = A;
if (A->lchild!=0&&A->lchild->value>Z->value){
Z = A->lchild;
}
if (A->rchild!=0&&A->rchild->value>Z->value){
Z = A->rchild;
}
if (Z!=A){
int z;
z = A->value;
A->value = Z->value;
Z->value = z;
update(Z);
}
return;
}
int main()
{
int n,m;
HBLT * tmp;
while(scanf("%d",&n)!=EOF){
for (int i=0;i<n;i++){
tmp = new HBLT();
tmp->lchild = 0;
tmp->rchild = 0;
tmp->dist = 0;
scanf("%d",&tmp->value);
parent[i] = tmp;
}
scanf("%d",&m);
int a,b;
for (int i=0;i<m;i++){
scanf("%d %d",&a,&b);
if (parent[a-1]!=parent[b-1]){
parent[a-1]->value = (parent[a-1]->value)/2;
parent[b-1]->value = (parent[b-1]->value)/2;
update(parent[a-1]);
update(parent[b-1]);
tmp = merge(parent[a-1],parent[b-1]);
printf("%d\n",tmp->value);
parent[a-1] = tmp;
parent[b-1] = tmp;
}else {
printf("-1\n");
}
}
delete[] parent;
}
return 0;
}