BZOJ 1455 罗马游戏

Posted on 2016-05-07 15:13  ziliuziliu  阅读(125)  评论(0编辑  收藏  举报

两点注意:

首先,pop一个点now,设fath[now]为当前堆顶节点。

其次,这题不保证两军团是否merge过。

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1000500
using namespace std;
int n,m,w[maxn],tree[maxn][3],fath[maxn],x,y,dis[maxn];
char s[3];
bool vis[maxn];
int find(int x)
{
    if(x!=fath[x])
        fath[x]=find(fath[x]);
    return fath[x];
}
void pushup(int x)
{
    int ls=tree[x][1],rs=tree[x][2];
    if (dis[ls]<dis[rs]) swap(tree[x][1],tree[x][2]);
    if (rs==0) dis[x]=0;
    else dis[x]=dis[rs]+1;
}
int merge(int a,int b)
{
    if (a==0) return b;
    if (b==0) return a;
    if (w[a]>w[b]) swap(a,b);
    tree[a][2]=merge(tree[a][2],b);
    fath[tree[a][2]]=a;
    pushup(a);
    return a;
}
void pop(int x)
{
    int ls=tree[x][1],rs=tree[x][2];
    tree[x][1]=tree[x][2]=dis[x]=0;
    fath[ls]=ls;fath[rs]=rs;
    int regis=merge(ls,rs);
    fath[x]=regis;
}
void work1()
{
    scanf("%d",&x);
    if (vis[x]) printf("0\n");
    else
    {
        int now=find(x);
        printf("%d\n",w[now]);
        vis[now]=true;
        pop(now);
    }
}
void work2()
{
    int regis;
    scanf("%d%d",&x,&y);
    if ((vis[x])||(vis[y])) return;
    int f1=find(x),f2=find(y);
    if (f1!=f2) 
        regis=merge(f1,f2);
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&w[i]);    
        fath[i]=i;
    }
    scanf("%d",&m);
    for (int i=1;i<=m;i++)
    {
        scanf("%s",s);
        if (s[0]=='K') work1();
        else work2();
    }
    return 0;
}