使用左偏树,套用模板即可。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 100005;
int father[MAXN]; //父结点
struct leftTree //左偏树
{
int lc, rc; //左孩子,右孩子
int value; //体力值
int dis; //距离
}tree[MAXN];
//查找结点x所在树的根结点
int find(int x)
{
if (x != father[x])
father[x] = find(father[x]);
return father[x];
}
//合并结点x所在树和结点y所在树
int merge(int x, int y)
{
if (x == 0) //结点x所在树为空
return y;
if (y == 0) //结点y所在树为空
return x;
if (tree[x].value < tree[y].value)
swap(x, y);
tree[x].rc = merge(tree[x].rc, y);
father[tree[x].rc] = x;
if (tree[tree[x].lc].dis < tree[tree[x].rc].dis)
swap(tree[x].lc, tree[x].rc);
if (tree[x].rc != 0)
tree[x].dis = tree[tree[x].rc].dis + 1;
else
tree[x].dis = 0;
return x;
}
//从树中删除结点x
int pop(int x)
{
int l = tree[x].lc;
int r = tree[x].rc;
father[l] = l;
father[r] = r;
tree[x].lc = tree[x].rc = tree[x].dis = 0;
return merge(l, r);
}
int main()
{
int n;
while (cin >> n)
{
memset(tree, 0, sizeof(tree));
for (int i = 1; i <= n; ++i)
{
cin >> tree[i].value;
father[i] = i;
}
int m;
cin >> m;
while (m--)
{
int x, y;
cin >> x >> y;
int fx = find(x);
int fy = find(y);
if (fx == fy) //两者根结点相同,即两者认识
{
cout << -1 << endl;
continue;
}
int rx = pop(fx);
tree[fx].value /= 2;
fx = merge(rx, fx);
int ry = pop(fy);
tree[fy].value /= 2;
fy = merge(ry, fy);
cout << tree[merge(fx, fy)].value << endl;
}
}
return 0;
}
继续加油。