• codeforces B. Online Meeting 解题报告


    题目链接:http://codeforces.com/problemset/problem/420/B

    题目意思:给出一段连续的消息记录:记录着哪些人上线或者下线。问通过给出的序列,找出可能为leader的人的编号。符合leader的条件是:至少有一个人上线的时候,绝对要有该人(leader)的存在。

          整个五一都把时间耗在这题里了......首先太感谢jhf大神,竟然可以这么有耐心的跟我这个陌生人讨论题目。但是,限于本人理解能力有点问题,在参考他写的代码里,还是有一些部分不太理解。

          以下结合我的理解来说。首先,将有可能为leader的人分成两批:没有在序列中出现过的 + 在序列中有可能是leader的候选人。要知道记录里没有出现过的人都有可能是leader。然后,对于候选人又分成两批:整个记录中的第一人 + 记录中的某一个人。对于记录中第一个人为leader的情况有两种: (1)整个记录里只有上线的人,没有下线的; (2)整个记录里每个人第一次出现都是以上线形式出现,但记录中存在下线。这个时候最有可能为leader 的 非第一个人莫属了。对于有可能是记录中的某一个人(有可能不是第一个),需要符合:这些候选人第一次出现以 下线形式出现。

          那总体的思路就是:挑出候选人,然后在候选人当中选出最后下线的,就是说,上线的人要在该人离开前都要下线。然后加上未出现过的人,就是答案了。

     补充:     终于找到他的原话 + 我的补充了:

    jhf:

    1、先预处理 ,例如+1 -2 补充完整为: +2+1-2-1   这两个是等价的(因为所有的人都是先上线再下线)。实质上就是把直接下线而没有先上线的人的上线记录加在前面,例如-2+3-3-4-1,2 4 1直接下线了,他们是唯一有可能当leader的,然后试图从中再筛选,筛选的方法就是看这些人有没有中途在还有人在线的时候就下线了

    2、然后遍历记录每走一条,淘汰那些不符合的人...

    最终版:

    x第一次出现是-x的形式的列为候选
     
     
    如果没有这种的,把记录中的第一个数列为候选
     
     
    然后开始进一步筛选
     
     
    筛选就看这些候选中有没有在有人在线的情况下下线的
     
     
    如果有就排除
     
     
    然后加上那些没在记录中出现过得人就是答案

    ...

     候选人在有人在线的情况下下线了

    答:

    用一个bool数组标记出候选人
    用一个int记录当前在线人数
    查bool数组判断他是不是候选人,再看在线人数
     
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cstring>
     5 using namespace std;
     6 
     7 const int MAX_MSG = 1e5 + 2;
     8 const int MAX_PEOPLE = 1e5 + 2;
     9 int people, msg, init_num;
    10 int ans[MAX_PEOPLE];
    11 bool vis[MAX_PEOPLE], wait[MAX_PEOPLE];     // vis[]: 针对整个记录中没有出现过的人;wait[]:记录第一次出现是离线的人的编号
    12 
    13 struct node
    14 {
    15     int id;
    16     bool on;
    17 }user[MAX_MSG];
    18 
    19 void Input()
    20 {
    21     char ch;
    22     scanf("%d%d", &people, &msg);
    23     for (int i = 1; i <= msg; i++)
    24     {
    25         cin >> ch >> user[i].id;
    26         user[i].on = (ch == '+');   // 代表该人第一次出现是上线的
    27     }
    28 }
    29 
    30 void Make_wait()     // 挑出候选人
    31 {
    32     memset(vis, 0, sizeof(vis));
    33     memset(wait, 0, sizeof(wait));
    34     bool did = false;
    35     init_num = 0;
    36     for (int i = 1; i <= msg; i++)
    37     {
    38         if (vis[user[i].id])
    39             continue;
    40         if (!user[i].on)
    41         {
    42             did = true;
    43             init_num++;     // 统计第一次出现是下线的人的数量
    44             wait[user[i].id] = true;
    45         }
    46         vis[user[i].id] = true;
    47     }
    48     if (!did)     // 候选人只有记录中的第一个人(不考虑!vis[])
    49         wait[user[1].id] = true;
    50 }
    51 
    52 void Work()  // 判断候选人
    53 {
    54     int on_num = init_num;   // 第一次出现是以下线方式出现的人,即候选人
    55     for (int i = 1; i <= msg; i++)
    56     {
    57         if (user[i].on)
    58         {
    59             on_num++;                 
    60             if (on_num == 1 && !wait[user[i].id])   // 这条语句令我十分不解,可能是代表候选人是记录中的第一个人
    61             {
    62                 memset(wait, 0, sizeof(wait));
    63             }
    64             continue;
    65         }
    66         on_num--;          
    67         if (!wait[user[i].id])     // 非候选人直接跳过
    68             continue;
    69         if (on_num > 0)            // 离线对应该人不是leader
    70             wait[user[i].id] = false;
    71     }
    72 }
    73 
    74 void Output()
    75 {
    76     int ans_num = 0;
    77     for (int i = 1; i <= people; i++)
    78     {
    79         if (!vis[i] || wait[i])
    80             ans[++ans_num] = i;
    81     }
    82     printf("%d
    ", ans_num);
    83     if (!ans_num)
    84         return;
    85     for (int i = 1; ans_num && i <= ans_num; i++)
    86         printf("%d ", ans[i]);
    87     puts("");
    88 }
    89  
    90 int main()
    91 {
    92     Input();
    93     Make_wait();
    94     Work();
    95     Output();
    96     return 0;
    97 }
  • 相关阅读:
    我们可以用微服务创建状态机吗?
    MyBatis 实现一对多有几种方式,怎么操作的?
    说几个 zookeeper 常用的命令?
    使用 RabbitMQ 有什么好处?
    消息基于什么传输?
    如何获取自动生成的(主)键值?
    vue打包压缩
    mysqldump数据库全备份_MySQL
    mysql的binlog
    开启BinLog_MySQL
  • 原文地址:https://www.cnblogs.com/windysai/p/3705720.html
Copyright © 2020-2023  润新知