|Hdu 1512|可并堆|并查集|Monkey King

来源:互联网 发布:冒泡排序 js 编辑:程序博客网 时间:2024/06/06 00:24

Hdu传送门
左偏树模板题,细节一定要注意

#include<cstdio>#include<algorithm>#include<cstring>#define ms(i,j) memset(i,j,sizeof i);using namespace std;const int MAXN = 100000 + 5;struct node{    int l, r;//左偏树左、右孩子编号     int dis, key;//左偏树距离,键值     int f;//并查集father }lt[MAXN];int n;int m;int find(int x) //并查集find {    return (x==lt[x].f) ? (x) : (lt[x].f = find(lt[x].f)); }void build(int rt, int v)//使rt初始化为v值 {    lt[rt].l = lt[rt].r = lt[rt].dis = 0;    lt[rt].key = v; lt[rt].f = rt;    if (rt==0) lt[rt].dis = -1;}int merge(int rtA, int rtB)//合并两棵树 {    if (rtA==0) return rtB;    if (rtB==0) return rtA;    if (lt[rtA].key<lt[rtB].key) swap(rtA, rtB);//大值左偏树要满足key(x)<key(parents[x])     lt[rtA].r = merge(lt[rtA].r, rtB);//A的右子树和B合并     int &l = lt[rtA].l, &r = lt[rtA].r;//利用引用减少代码量,更加清晰    lt[l].f = lt[r].f = rtA; //更新并查集     if (lt[l].dis<lt[r].dis) swap(l, r);//需要满足左偏性质dis(lc)>=dis(rc)     if (r==0) lt[rtA].dis = 0; else lt[rtA].dis = lt[r].dis+1;//算距离     return rtA;}int del(int rt)//删除rt节点 {    int l = lt[rt].l;    int r = lt[rt].r;    lt[l].f = l;    lt[r].f = r;    lt[rt].l = lt[rt].r = lt[rt].dis = 0;    return merge(l, r);}int main(){    while (scanf("%d", &n)==1)    {        for (int i=1;i<=n;i++)        {            int x;            scanf("%d", &x);            build(i, x);        }        build(0, 0);        scanf("%d", &m);        for (int i=1;i<=m;i++)        {            int x,y;            scanf("%d%d", &x, &y);            int x1 = find(x);            int x2 = find(y);//找最强壮的             if (x1==x2) {printf("-1\n");continue;}            lt[x1].key>>=1;            lt[x2].key>>=1;//之后插入的值             int left = del(x1), right = del(x2);            left = merge(left, x1), right = merge(right, x2);            left = merge(left, right);            printf("%d\n", lt[left].key);        }    }    fclose(stdin);fclose(stdout);    return 0;}
0 0