• bzoj1455&&luogu2713罗马游戏


    罗马游戏

    题目描述

      罗马皇帝很喜欢玩杀人游戏。 他的军队里面有n个人,每个人都是一个独立的团。最近举行了一次平面几何测试,每个人都得到了一个分数。 皇帝很喜欢平面几何,他对那些得分很低的人嗤之以鼻。

      他决定玩这样一个游戏。 它可以发两种命令:

    1. Merger(i, j)。把i所在的团和j所在的团合并成一个团。如果i, j有一个人是死人,那么就忽略该命令。
    2. Kill(i)。把i所在的团里面得分最低的人杀死。如果i这个人已经死了,这条命令就忽略。

      皇帝希望他每发布一条kill命令,下面的将军就把被杀的人的分数报上来。(如果这条命令被忽略,那么就报0分)

    输入输出格式

    输入格式:

      第一行一个整数n(1<=n<=1000000)。n表示士兵数,m表示总命令数。

      第二行n个整数,其中第i个数表示编号为i的士兵的分数。(分数都是[0..10000]之间的整数)

      第三行一个整数m(1<=m<=100000) 第3+i行描述第i条命令。命令为如下两种形式: 1. M i j 2. K i

    输出格式:

      如果命令是Kill,对应的请输出被杀人的分数。(如果这个人不存在,就输出0)

    输入输出样例

    输入样例:
        5
        100 90 66 99 10
        7
        M 1 5
        K 1
        K 1
        M 2 3
        M 3 4
        K 5
        K 4
    

      

    输出样例:
        10
        100
        0
        66
    

      分析:很明显这是一道可并堆的经典题目,题目字面翻译过来就是合并小根堆,并且查询最小值后删除最小值,比较简单,类似于板子题。

    #include <stdio.h>
    #include <algorithm>
    using namespace std;
    int dis[1000001];
    int num[1000001];
    int son[1000001][2];
    int fa[1000001];
    bool kill[1000001];
    int n,m;
    int find(int p)
    {
        if(fa[p]==0) return 0;
        return (fa[p]==p)?p:fa[p]=find(fa[p]);
    }
    int merge(int x,int y)
    {
        if(!x) return y;
        if(!y) return x;
        if(num[x]>num[y]) swap(x,y);
        son[x][1]=merge(son[x][1],y);
        if(dis[son[x][1]]>dis[son[x][0]])
            swap(son[x][1],son[x][0]);
        dis[x]=dis[son[x][1]]+1;
        return x;
    }
    int main()
    {
        dis[0]=-1;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&num[i]),fa[i]=i;
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            int a,b;
            char kind[2];
            scanf("%s",kind);
            if(kind[0]=='M')
            {
                scanf("%d%d",&a,&b);
                if(kill[a]||kill[b]) continue;
                a=find(a),b=find(b);
                if(a!=b) fa[a]=fa[b]=merge(a,b);
            }
            else
            {
                scanf("%d",&a);
                if(kill[a])
                {
                    printf("0
    ");
                    continue;
                }
                int rt;
                printf("%d
    ",num[rt=find(a)]);
                kill[rt]=true;
                b=son[rt][0],a=son[rt][1];
                fa[rt]=fa[a]=fa[b]=merge(a,b);
            }
        }
    }
    

      

  • 相关阅读:
    nyoj 329 循环小数【KMP】【求最小循环节长度+循环次数+循环体】
    转 :hdoj 4857 逃生【反向拓扑】
    hdoj 3342 Legal or Not【拓扑排序】
    hdoj 2094 产生冠军
    poj 1789 Truck History【最小生成树prime】
    转:【拓扑排序详解】+【模板】
    hdoj 1285 确定比赛名次【拓扑排序】
    poj 2031 Building a Space Station【最小生成树prime】【模板题】
    zzuoj 10408: C.最少换乘【最短路dijkstra】
    [LC] 232. Implement Queue using Stacks
  • 原文地址:https://www.cnblogs.com/yangsongyi/p/8893005.html
Copyright © 2020-2023  润新知