zoukankan      html  css  js  c++  java
  • [题解]Codeforces Round #709 (Div. 1, based on Technocup 2021 Final Round)

    【题目】

    A. Basic Diplomacy

    【描述】

    Aleksey有n个朋友,有一个m天的假期,每天都需要一个朋友来陪他。给出每天有空的朋友的编号,要求同一个朋友来的天数不能超过m/2上取整。求是否有一个朋友到访的方案,没有输出“NO”,有输出“YES”并输出任意一种方案。

    数据范围:1<=n,m<=100000,保证每天至少有一个朋友有空,共t组数据,1<=t<=10000

    【思路】

    这道题只要注意到“同一个朋友来的天数不能超过m/2上取整”的要求就很简单了。

    首先,由于总天数是m,所以随意一种方案,最多就只有一个朋友来的天数超过了这个上界,我们不妨称这个来太多次的朋友为zyy;于是我们只需要让zyy少来几次就行了。

    于是我们遍历zyy具体来的那些天,尝试替换成当天有空的别的朋友来;只需要替换到zyy来的天数恰好为m/2上取整就可以不再替换了。

    然后我们来看看,如果上述替换能够成功(就是能够替换到zyy来的天数恰好为m/2上取整),新的方案能否满足要求?答案是肯定的。因为新方案中zyy一共来了m/2上取整天,剩余的m-(m/2上取整)天<=m/2上取整天,换言之即使剩余的每一天都是同一个人来,也是符合要求的。

    而如果上述替换不能成功(就是无论如何调整,zyy来的天数都要多于m/2上取整),那么很显然没有符合要求的方案。

    现在,我们来考虑替换方法。根据上述分析,聪明的读者已经发现,只要在zyy来的那些天里,找到足够的天数同时有别的朋友也有空就行了。于是我们遍历zyy具体来的那些天,一旦某一天有别的朋友有空,我们就让别的朋友替换zyy在那一天来,直到zyy来的天数恰好为m/2上取整,或者替换不成功;由于本题的上界是“不能超过m/2上取整”,保证了不会同时出现超限的两个朋友,也保证了不会让一个朋友符合要求而导致另一个朋友超限,于是遍历的顺序不会导致错误(所以顺序遍历就ok啦),替换成的别的朋友的选择也可以很随意(只要不是zyy就ok啦)。

    以上就是本题的解题思路。但是,聪明的读者或许发现了一个小猫腻:只需记住每天有最多哪两个朋友有空就可以啦!这实际上也是由上界“不能超过m/2上取整”带来的小性质。

    思路说清楚了,实现很简单,就不赘述了,不清楚可以参考一下下面的代码。每组的复杂度为O(m*n),也就是读数据的复杂度了。

    (老年人zyy一开始没注意到上界“不能超过m/2上取整”的性质,一开始想贪心,觉得不对,又想要不还是搜索+剪枝吧,写到一半才发现这个性质,果然是脑子不行了……)

    【我的实现】

    复杂度:每组数据O(m*n)

      1 //#define _CRT_SECURE_NO_WARNINGS
      2 
      3 #include <iostream>
      4 #include <cstdio>
      5 #include <algorithm>
      6 #include <cmath>
      7 #include <string>
      8 #include <cstring>
      9 #include <cstdlib>
     10 #include <vector>
     11 #include <list>
     12 #include <map>
     13 #include <queue>
     14 #include <stack>
     15 #include <set>
     16 
     17 #define PRO 'A'
     18 //#define PRO 'B'
     19 //#define PRO 'C'
     20 //#define PRO 'D'
     21 //#define PRO 'E'
     22 //#define PRO 'F'
     23 //#define PRO 'G'
     24 //#define PRO 'H'
     25 //#define PRO 'I'
     26 
     27 
     28 using namespace std;
     29 
     30 #if (PRO == 'A')
     31 
     32 #define N 100000
     33 #define M 100000
     34 
     35 int cnt[N];
     36 int fri[M][2], ans[M];
     37 
     38 
     39 #endif // (PRO == 'A')
     40 
     41 #if (PRO == 'B')
     42 
     43 #endif // (PRO == 'B')
     44 
     45 #if (PRO == 'C')
     46 
     47 #endif // (PRO == 'C')
     48 
     49 #if (PRO == 'D')
     50 
     51 #endif // (PRO == 'D')
     52 
     53 #if (PRO == 'E')
     54 
     55 #endif // (PRO == 'E')
     56 
     57 #if (PRO == 'F')
     58 
     59 #endif // (PRO == 'F')
     60 
     61 #if (PRO == 'G')
     62 
     63 #endif // (PRO == 'G')
     64 
     65 #if (PRO == 'H')
     66 
     67 #endif // (PRO == 'H')
     68 
     69 #if (PRO == 'I')
     70 
     71 #endif // (PRO == 'I')
     72 
     73 
     74 int main()
     75 {
     76 #if (PRO == 'A')
     77     int T;
     78     int n, m;
     79     int i, j;
     80     int tmp, tmp2;
     81     int fri_num;
     82     
     83     scanf("%d", &T);
     84     while (T--) {
     85         fri_num = -1;
     86         memset(cnt, 0, sizeof(cnt));
     87         scanf("%d%d", &n, &m);
     88         for (i = 0; i < m; i++) {
     89             scanf("%d", &tmp);
     90             if (tmp == 1) {
     91                 scanf("%d", &fri[i][0]);
     92                 fri[i][1] = -1;
     93             }
     94             else {
     95                 scanf("%d%d", &fri[i][0], &fri[i][1]);
     96                 for (j = 2; j < tmp; j++) {
     97                     scanf("%d", &tmp2);
     98                 }
     99             }
    100             ans[i] = fri[i][0];
    101             cnt[ans[i]]++;
    102             if (cnt[ans[i]] > (m + 1) / 2) {
    103                 fri_num = ans[i];
    104             }
    105         }
    106         if (fri_num != -1) {
    107             for (i = 0; i < m; i++) {
    108                 if (ans[i] == fri_num && fri[i][1] != -1) {
    109                     ans[i] = fri[i][1];
    110                     cnt[fri_num]--;
    111                     cnt[fri[i][1]]++;
    112                     if (cnt[fri_num] <= (m + 1) / 2) {
    113                         break;
    114                     }
    115                 }
    116             }
    117         }
    118         if (fri_num != -1 && cnt[fri_num] > (m + 1) / 2) {
    119             printf("NO
    ");
    120         }
    121         else {
    122             printf("YES
    ");
    123             for (i = 0; i < m; i++) {
    124                 printf("%d ", ans[i]);
    125             }
    126             printf("
    ");
    127         }
    128     }
    129     //cout << "Hello World!
    ";
    130 #endif // (PRO == 'A')
    131 
    132 #if (PRO == 'B')
    133 
    134     //cout << "Hello World!
    ";
    135 #endif // (PRO == 'B')
    136 
    137 #if (PRO == 'C')
    138 
    139     //cout << "Hello World!
    ";
    140 #endif // (PRO == 'C')
    141 
    142 #if (PRO == 'D')
    143 
    144     //cout << "Hello World!
    ";
    145 #endif // (PRO == 'D')
    146 
    147 #if (PRO == 'E')
    148 
    149     //cout << "Hello World!
    ";
    150 #endif // (PRO == 'E')
    151 
    152 #if (PRO == 'F')
    153 
    154     //cout << "Hello World!
    ";
    155 #endif // (PRO == 'F')
    156 
    157 #if (PRO == 'G')
    158 
    159     //cout << "Hello World!
    ";
    160 #endif // (PRO == 'G')
    161 
    162 #if (PRO == 'H')
    163 
    164 
    165 #endif // (PRO == 'H')
    166 
    167 #if (PRO == 'I')
    168 
    169     //cout << "Hello World!
    ";
    170 #endif // (PRO == 'I')
    171 
    172 
    173     //cout << "Hello World!
    ";
    174     return 0;
    175 }
    View Code

    【评测结果】

    ps. 几百年没有登过cf了。最近不太开心,恰巧清理邮箱时看到一大堆cf的邮件,就登上去看了看,密码竟然还记得(不像博客园,试了好几次之后只好找回密码,还被迫绑定了手机号)。随意点开了之前的一场div1的比赛,从踌躇满志到无奈苦笑,搞了好久才搞出来第一题,老年人的思维复建过程令人羞愧,心想还好没有鲁莽地注册比赛,否则本就不高的排名怕是要掉到姥姥家了。感觉这道题有些意思,所以来记录一下(虽然想来这样简单的题目的题解大概是不会有人看的吧)。讲不清自己是怎么一步一步选择了现在的生活状态,虽说谈不上不喜欢,但似乎确实没有过以前搞竞赛时A题的快乐了,取得的成绩从各种意义上也算不上好看,也许真的就是不适合吧。下次更新不知道又是什么时候了,希望下次能够开心一点。

  • 相关阅读:
    git command
    互联网应用架构概览-学习笔记
    机器学习基础概念-阿里大学课程学习笔记
    Python的并行求和例子
    C语言处理CSV数据
    Pattern Evaluation
    Python写的大小写转换小工具
    处理输入为非对角阵的Clustering by fast search and find of density peak代码
    css点击下层穿透上层元素
    浏览器全屏效果
  • 原文地址:https://www.cnblogs.com/CQBZOIer-zyy/p/14615456.html
Copyright © 2011-2022 走看看