zoukankan      html  css  js  c++  java
  • Codeforces Round #709 (div.2) A B C

    第7分钟过A,第48分钟过B,然后憋到结束也没出C.
    惨啊.

    A

    这是我在CF上见到的实现起来最简单的题目了.
    会发现,想要达成"任意一个格子都有逃离的路线"意味着不能存在某一区域被墙圈住,如果把墙看作边,把格子的顶点看作节点,那么就转化为最终的(无向)图中不能存在环.
    给定了一定数量的节点,要求在其中添加尽可能多的边,并且不能存在环.这显然会形成树,边数即为节点数-1.
    之后只需要根据a,b计算出原有墙数x,节点数y,输出x-(y-1)即可.发现计算结果即为a*b.

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    int a, b;
    
    void solve(){
    	scanf("%d%d", &a, &b);
    	printf("%d
    ", a * b);
    }
    
    int main(){
    	int t;
    	scanf("%d", &t);
    	while(t--) solve();   
    
    	return 0;
    }
    

    B

    先推导一波观察一下,a[1]=s%m,a[2]=(a[1]+c)%=(s%m+c)%m=(s+c)%m,可知a[i]=(s+(i-1)c)%m.
    会看出来,对于任意一个存在解的数组,a[i]-a[i-1]的值域只有两个或者一个值.其中,只有一个值的情况对应的数组为等差数列,这是m显然可取正无穷.
    而对于值域有两个值的情况下:
    1 9 17 6 14 3
    a[i]-a[i-1]:8 8 -11 8 -11
    发现解即为m=8-(-11)=19,c=8.这个结论具有普遍性.

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    int n, a[100010];
    
    void solve() {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%d", a + i);
        if (n <= 2) {
            puts("0");
            return;
        }
    
        bool b1 = false, b2 = false;
        int v1, v2;
        int big = 0;
        for (int i = 1; i <= n; i++) {
            big = max(big, a[i]);
            if (i == 1) continue;
            if (!b1) {
                b1 = true, v1 = a[i] - a[i - 1];
            } else if (!b2) {
                b2 = true, v2 = a[i] - a[i - 1];
            } else if (a[i] - a[i - 1] != v1 && a[i] - a[i - 1] != v2) {
                if (v1 == v2)
                    v2 = a[i] - a[i - 1];
                else {
                    puts("-1");
                    // printf("!!!%d %d
    ", v1, v2);
                    return;
                }
            }
        }
    
        if (v1 > v2) swap(v1, v2);
        if (v1 == v2)
            puts("0");
        else if (v2 - v1 > big)
            printf("%d %d
    ", v2 - v1, v2);
        else
            puts("-1");
    }
    
    int main() {
        int t;
        scanf("%d", &t);
        while (t--) solve();
    
        return 0;
    }
    

    实际上这显然是一个适合使用unordered_set的场景,参考这篇补题.

    C

    思维力不够,赛时没做出来.一直没有注意到m/2含有的特殊意义.
    一旦有某人出现了m/2次后,剩余的人就不可能出现m/2次了.这是突破口.
    并且显然地,如果发现某人可选的天数不超过m/2,可以直接让他出席其中所有闲置的天.
    得到如下流程:
    依次检查每个人的出现次数是否超过m/2
      否-使其出席所有可出席天
      是-检查有多少天只有他一人可出席
        不超过m/2-先出席这些天,再出席其它天直至此人共计出席了m/2天,且此后处理任何人时只需使其出席其所有闲置可选天
        超过m/2-本组数据无解
    最后需要检查一下是否所有天都安排上了.

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <vector>
    using namespace std;
    
    vector<int> d[100010];  // who appeared on day i
    vector<int> p[100010];  // people i appeared on which day
    int n, m, ct[100010];   // appear time of people
    int ans[100010];
    
    void solve() {
        scanf("%d%d", &n, &m);
        memset(ans, 0, sizeof(ans));
        memset(ct, 0, sizeof(ct));
        for (int i = 1; i <= n; i++) p[i].clear();
        for (int i = 1; i <= m; i++) {
            d[i].clear();
            int k, x;
            scanf("%d", &k);
            while (k--) {
                scanf("%d", &x);
                d[i].push_back(x);
                p[x].push_back(i);
                ct[x]++;
            }
        }
    
        int bd = (m - 1) / 2 + 1;
        bool good = false;
        for (int i = 1; i <= n; i++) {
            if (good) {
                for (auto j : p[i])
                    if (!ans[j]) ans[j] = i;
            } else if (ct[i] <= bd)
                for (auto j : p[i]) ans[j] = i;
            else {
                good = true;
                int c = 0;
                for (int j = 1; j <= m; j++)
                    if (!ans[j] && d[j].size() == 1 && d[j][0] == i) {
                        ans[j] = i;
                        c++;
                    }
                if (c > bd) {
                    puts("NO");
                    return;
                }
                for (auto j : p[i]) {
                    if (c == bd) break;
                    if (!ans[j]) {
                        ans[j] = i;
                        c++;
                    }
                }
            }
        }
    
        for (int i = 1; i <= m; i++)
            if (!ans[i]) {
                puts("NO");
                return;
            }
        puts("YES");
        for (int i = 1; i <= m; i++) printf("%d ", ans[i]);
        puts("");
    }
    
    int main() {
        int t;
        scanf("%d", &t);
        while (t--) solve();
    
        return 0;
    }
    

    总结就是注意系数,并且敢于假设前提,往后多想几步.
    不能一厢情愿地认为是某种算法,这可能是一道构造题.

  • 相关阅读:
    Redis未授权访问攻击过程与防范
    Redis安装
    Connection closing...Socket close. Connection closed by foreign host. Disconnected from remote host(centos6.9) at 14:59:05.
    windows远程xshell文件上传下载:
    Linux重置MySQL密码
    nginx rewrite 实现URL跳转
    Openstack 清除openstack网络与路由 (十七)
    创建 OpenStack云主机 (十五)
    OpenStack 存储服务 Cinder存储节点部署LVM (十四)
    OpenStack 存储服务 Cinder介绍和控制节点部署 (十三)
  • 原文地址:https://www.cnblogs.com/Gaomez/p/14564412.html
Copyright © 2011-2022 走看看