• 【BZOJ1455】罗马游戏-斜堆/左偏树-并查集(+数据生成器)


    Problem 遗产

    题目大意

    罗马皇帝很喜欢玩杀人游戏。 他的军队里面有n个人,每个人都是一个独立的团。最近举行了一次平面几何测试,每个人都得到了一个分数。 皇帝很喜欢平面几何,他对那些得分很低的人嗤之以鼻。他决定玩这样一个游戏。 它可以发两种命令: 1. Merger(i, j)。把i所在的团和j所在的团合并成一个团。如果i, j有一个人是死人,那么就忽略该命令。 2. Kill(i)。把i所在的团里面得分最低的人杀死。如果i这个人已经死了,这条命令就忽略。 皇帝希望他每发布一条kill命令,下面的将军就把被杀的人的分数报上来。(如果这条命令被忽略,那么就报0分)

    Solution

    写一个并查集维护每个人所在的团,一个died数组判断每个人有没有死掉。

    在此基础之上对每一个团建一个左偏树/斜堆优化查询最小值的过程,支持合并。

    对于每一个合并操作只要将两个斜堆合并即可。

    挺简单的一个裸题。

    Datamaker

    这一题题目其实是有问题的。

    如果分数范围为1~10000,那么1000000个人中会有非常多个人是重分的。

    仔细思考一下我们就会知道,重分情况下罗马皇帝也不知道会杀谁。

    所以数据合法情况下这题没有人能够AC,甚至标程也是错的。

    所以我将分数范围调整为1~10000000且没有人会重分。

     1 #include <ctime>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstdio>
     5 
     6 #define MAXN 1000000
     7 #define MAXP 10000000
     8 #define MAXM 100000
     9 
    10 bool get[MAXP];
    11 using namespace std;
    12 
    13 int randint(){
    14     return ((long long)rand()*9971+rand())%1000007;
    15 }
    16 int main(){
    17     freopen("bzoj1455.in","w",stdout);
    18     srand(time(NULL));
    19     printf("%d
    ",MAXN);
    20     for(int i=1;i<=MAXN;i++){
    21         int p=randint()%(MAXP-1)+1;
    22         while(get[p]){
    23             p=randint()%(MAXP-1)+1;    
    24         }
    25         printf("%d ",p);
    26         get[p]=1;
    27     }
    28     printf("%d
    ",MAXM);
    29     for(int i=1;i<=MAXM;i++){
    30         if(rand()%2==0){
    31             printf("M ");
    32             int x=randint()%(MAXN-1)+1,y=randint()%(MAXN-1)+1;
    33             if(x==y)y++;
    34             printf("%d %d
    ",x,y);
    35         }else{
    36             printf("K ");
    37             printf("%d
    ",randint()%(MAXN-1)+1);
    38         }
    39     }
    40 }

    AC Code

    #include <iostream>
    #include <cstdio>
    using namespace std;
    struct soldier{
        int fa,died,l,r,v;
    }a[1000010];
    int n,m,x,y,nx,ny,p;
    char tsk[2];
    int find(int x){
        return (a[x].fa==x)?x:a[x].fa=find(a[x].fa);
    }
    int merge(int x,int y){
        if(!x)return y;
        if(!y)return x;
        if(a[x].v>a[y].v)swap(x,y);
        a[x].r=merge(a[x].r,y);
        swap(a[x].l,a[x].r);
        return x; 
    }
    int main(){
    //  freopen("bzoj1455.in","r",stdin);
    //  freopen("bzoj1455.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i].v);
        for(int i=1;i<=n;i++)a[i].fa=i;
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            scanf("%s",tsk);
            if(tsk[0]=='M'){
                scanf("%d%d",&x,&y);
                if(!a[x].died&&!a[y].died){
                    nx=find(x),ny=find(y);
                    if(nx!=ny)a[nx].fa=a[ny].fa=merge(nx,ny);
                }
            }else{ 
                scanf("%d",&x);
                if(!a[x].died){
                    p=find(x);
                    a[p].died=1;
                    printf("%d
    ",a[p].v);
                    a[p].fa=merge(a[p].l,a[p].r);
                    a[a[p].fa].fa=a[p].fa;
                }else printf("0
    ");
            }
        }
    }
  • 相关阅读:
    韩寒做错了(update 4 12)。
    放弃IE6。
    阿弥陀佛,我没有“抄袭”。
    婚姻。
    爆牙齿饭否?
    地震之后——和妈妈对话。
    8年前,《西班牙,我为你哭泣。》
    在等决赛中提问。
    地震之后——中国互联网在黑夜中哭泣。
    年轻。
  • 原文地址:https://www.cnblogs.com/skylynf/p/7277709.html
Copyright © 2020-2023  润新知