zoukankan      html  css  js  c++  java
  • [BZOJ1455] 罗马游戏

    Time Limit: 5 Sec  Memory Limit: 64 MB
    Submit: 1994  Solved: 865
    [Submit][Status][Discuss]

    Description

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

    Input

    第一行一个整数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

    Output

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

    Sample Input

    5
    100 90 66 99 10
    7
    M 1 5
    K 1
    K 1
    M 2 3
    M 3 4
    K 5
    K 4

    Sample Output

    10
    100
    0
    66

    HINT

    部分数据如下 JudgeOnline/upload/201607/aa.rar

    思路

    左偏树

    一种一直在右儿子插入,右儿子太长了就交换左右子的二叉堆;

    s[]维护堆性质的关键字;

    d[]维护左偏性质的距离(当前节点到最近的叶节点所需经过的边数);

    代码实现

     1 #include<cstdio>
     2 const int maxn=1e6+10;
     3 int n,m;
     4 int f[maxn],s[maxn],d[maxn],l[maxn],r[maxn];
     5 inline void swap_(int&x,int&y){x^=y,y^=x,x^=y;}
     6 int ff(int x){return f[x]==x?x:f[x]=ff(f[x]);}
     7 int merger(int a,int b){
     8     if(!a) return b;
     9     if(!b) return a;
    10     if(s[a]>s[b]) swap_(a,b);
    11     r[a]=merger(r[a],b);
    12     if(d[r[a]]>d[l[a]]) swap_(l[a],r[a]);
    13     d[a]=d[r[a]]+1;
    14     return a;
    15 }
    16 int a,b;
    17 char ch[3];
    18 int main(){
    19     scanf("%d",&n);
    20     for(int i=1;i<=n;i++) scanf("%d",&s[i]),f[i]=i;
    21     scanf("%d",&m);
    22     while(m--){
    23         scanf("%s",ch);
    24         if(ch[0]=='M'){
    25             scanf("%d%d",&a,&b);
    26             if(s[a]==-1||s[b]==-1) continue;
    27             a=ff(a),b=ff(b);
    28             if(a!=b)
    29             f[a]=f[b]=merger(a,b);
    30         }
    31         if(ch[0]=='K'){
    32             scanf("%d",&a);
    33             if(s[a]!=-1){
    34                 a=ff(a);
    35                 printf("%d
    ",s[a]);s[a]=-1;
    36                 f[a]=merger(l[a],r[a]);
    37                 f[f[a]]=f[a];
    38             }
    39             else puts("0");
    40         }
    41     }
    42     return 0;
    43 }
    1455 Accepted 20352 kb 2332 ms C++/Edit 1189 B 2017-06-08 21:18:39
  • 相关阅读:
    b_lc_长度为 3 的不同回文子序列(统计两个相同字符中间有多少个不同字符)
    b_lc_最小未被占据椅子的编号(记录每个时间来的人 + pq)
    b_lc_统计好数字的数量(排列数+组合数+快速幂)
    TreeMap
    LinkedHashMap
    HashMap的总结
    HashMap
    Collection
    Map
    LinkedList学习
  • 原文地址:https://www.cnblogs.com/J-william/p/6964711.html
Copyright © 2011-2022 走看看