【BZOJ1455】罗马游戏 可并堆

链接:

#include <stdio.h>
int main()
{
    puts("转载请注明出处[vmurder]谢谢");
    puts("网址:blog.csdn.net/vmurder/article/details/44513511");
}

题解:

可并堆:
其实它只是个函数,而不是数据结构,它的数据结构只是“堆”?
可并的随机堆才算一个?

两个堆合并时,对比大小决定谁是父亲,然后劣的和优的 的子再递归进行比较,直到一头为空(无法也不用再比较时),能满足正常插入就可以保证二叉的性质时停止。

代码:

可并随机堆(随机挂到某子上)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1001000
#define inf 0x3f3f3f3f
using namespace std;
struct Merge_Heap
{
    int son[N][2],val[N];
    bool be_killed[N];

    int fa[N];
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    void init(int n)
    {
        val[0]=inf;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&val[i]);
            fa[i]=i;
        }
    }
    int merge(int x,int y) // 小根随机可并堆
    {
        if(val[x]>val[y])swap(x,y);
        if((x&&y)==0)return x;
        int k=rand()&1;
        son[x][k]=merge(son[x][k],y);
        return x;
    }
    void kill()
    {
        int x;
        scanf("%d",&x);
        if(be_killed[x])
        {
            puts("0");
            return ;
        }
        x=find(x);
        be_killed[x]=1;
        printf("%d\n",val[x]);
        int k=merge(son[x][0],son[x][1]);
        if(k)fa[x]=fa[son[x][0]]=fa[son[x][1]]=k;
    }
    void battle()
    {
        int x,y;
        scanf("%d%d",&x,&y);
        if(be_killed[x]||be_killed[y])return ;
        if(find(x)==find(y))return ;
        fa[fa[x]]=fa[fa[y]]=merge(fa[x],fa[y]);
    }
}heap;
int n,m;
char opt[5];
int main()
{
// freopen("test.in","r",stdin);

    srand(252503);
    int i,k;
    scanf("%d",&n);
    heap.init(n);

    for(scanf("%d",&m);m--;)
    {
        scanf("%s",opt);
        if(opt[0]=='K')heap.kill();
        else heap.battle();
    }
    return 0;
}

你可能感兴趣的:(BZOJ1455,罗马游戏,可并堆)