• Codeforces Round #668 (Div. 2)【ABCD】


    比赛链接:https://codeforces.com/contest/1405

    A. Permutation Forgery

    题意

    给出一个大小为 $n$ 的排列 $p$,定义

    egin{equation} F(p)=mathrm{sort}([p_1+p_2,p_2+p_3,ldots,p_{n-1}+p_n]) 。 onumber end{equation}

    试找出一个不同于 $p$ 的 $p'$ 满足 $F(p') = F(p)$ 。

    题解

    反转 $p$ 即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int t;
        cin >> t;
        while (t--) {
            int n;
            cin >> n;
            vector<int> a(n);
            for (int i = 0; i < n; i++)
                cin >> a[i];
            reverse(a.begin(), a.end());
            for (int i = 0; i < a.size(); i++)
                cout << a[i] << " 
    "[i == a.size() - 1];
        }
        return 0;
    }

    B. Array Cancellation

    题意

    给出一个大小为 $n$,满足 $sum_{i=0}^{n-1} a_i = 0$ 的数组 $a$,每次可选择的操作如下:

    • 选择 $i < j$,将 $a_i$ 减一,$a_j$ 加一,花费为 $0$
    • 选择 $i > j$,将 $a_i$ 减一,$a_j$ 加一,花费为 $1$

    问将 $a_i$ 均变为 $0$ 的最小花费是多少。

    题解一

    分别存储正数和负数的位置,然后贪心加双指针模拟。

    代码

    #include <bits/stdc++.h.>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int t;
        cin >> t;
        while (t--) {
            int n;
            cin >> n;
            vector<int> a(n);
            vector<int> posi, nega;
            for (int i = 0; i < n; i++) {
                cin >> a[i];
                if (a[i] > 0) posi.push_back(i);
                if (a[i] < 0) nega.push_back(i);
            }
            int j = 0;
            for (int i = 0; i < int(posi.size()); i++) {
                while (a[posi[i]] > 0) {
                    while (j < int(nega.size()) and nega[j] < posi[i])
                        ++j;
                    if (j == int(nega.size())) break;
                    int mi = min(a[posi[i]], -a[nega[j]]);
                    a[posi[i]] -= mi;
                    a[nega[j]] += mi;
                    if (a[nega[j]] == 0) ++j;
                }
            }    
            long long ans = 0;
            for (int i = 0; i < n; i++)
                if (a[i] > 0) ans += a[i];        
            cout << ans << "
    ";
        }
        return 0;
    } 

    题解二

    最小负前缀的绝对值即为最少花费。

    证明

    对于最小负前缀,内部操作不会影响该负前缀的总和,涉及外部操作的最佳方案就是对负前缀加一,因为 $sum_{i=0}^{n-1} a_i = 0$,所以此时后缀为正且绝对值与该负前缀相等,将二者各视为一个整体操作即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int t;
        cin >> t;
        while (t--) {
            int n;
            cin >> n;
            long long ans = 0, cur = 0;
            for (int i = 0; i < n; i++) {
                int x;
                cin >> x;
                cur += x;
                ans = min(ans, cur);
            }
            cout << -ans << "
    ";
        }
        return 0;
    }

    C. Balanced Bitstring

    题意

    如果一个偶数长 $k$ 的二进制串有 $frac{k}{2}$ 个 $0$ 和 $1$,那么称这个二进制串为 $k$ 平衡串。给出一个由 $0,1,?$ 组成的字符串 $s$,$s$ 中的 $?$ 可被替换为 $0$ 或 $1$,判断 $s$ 是否可能为 $k$ 平衡串。

    题解

    因为共享中间的 $k-1$ 个字符,所以 $s_i = s_{i+k}$ 。

    所以如果第一个 $k$ 长子串确定合法,则整个字符串确定合法。

    另外还需枚举 $k$ 个起点并判断一开始的字符串中步长为 $k$ 的路径上的所有字符是否相同。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int t;
        cin >> t;
        while (t--) {
            int n, k;
            cin >> n >> k;
            string s;
            cin >> s;
            bool ok = true;
            int zero = 0, one = 0;
            for (int i = 0; i < k; i++) {
                bool a0 = false, a1 = false;
                for (int j = i; j < n; j += k)
                    if (s[j] != '?')
                        (s[j] == '0' ? a0 : a1) = true;
                if (a0 and a1)
                    ok = false;
                else if (a0 or a1)
                    ++(a0 ? zero : one);
            }
            if (max(zero, one) > k / 2)
                ok = false;
            cout << (ok ? "YES" : "NO") << "
    ";
        }
        return 0;
    }

    D. Tree Tag

    题意

    给出一颗树,Alice在结点 $a$,每次可以走的距离最多为 $da$,Bob在结点 $b$,每次可以走的距离最多为 $db$,Alice先走,问在无限步内Alice能否走到Bob的位置。

    题解

    Alice获胜的三种情况:

    • 一开始Bob在Alice的覆盖半径内,因为Alice先手,所以一步就可以走到Bob的位置
    • Alice的覆盖直径大于等于树的直径,此时Alice可以移到树的中心并覆盖树上的每一个点
    • Alice的覆盖直径大于等于Bob的步长,此时以Alice的起点为根节点,Bob无法超出Alice的覆盖范围移到另一颗子树

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int t;
        cin >> t;
        while (t--) {
            int n, a, b, da, db;
            cin >> n >> a >> b >> da >> db;
            --a, --b;
            vector<vector<int>> G(n);
            for (int i = 0; i < n - 1; i++) {
                int u, v;
                cin >> u >> v;
                --u, --v;
                G[u].push_back(v);
                G[v].push_back(u);
            }
            int diam = 0;
            vector<int> dep(n);
            function<int(int, int)> dfs = [&](int u, int p) {
                int len = 0;
                for (auto v : G[u]) {
                    if (v != p) {
                        dep[v] = dep[u] + 1;
                        int cur = 1 + dfs(v, u);
                        diam = max(diam, cur + len);
                        len = max(len, cur);
                    }
                }
                return len;
            };
            dfs(a, -1);
            cout << (2 * da >= min(diam, db) or dep[b] <= da ? "Alice" : "Bob") << "
    ";
        }
        return 0;
    }
  • 相关阅读:
    企业微信api接口调用-触发推送企业微信微信好友
    企业微信api接口调用-触发推送企业微信微信好友
    企业微信api接口调用-企业微信好友收发消息
    抖音api接口调用-同步抖音推荐的好友
    <转载>医学图像存储与传输系统(PACS)
    <转载>RESTful API 最佳实践
    <转载>DICOMweb——将DICOM影像接入互联网
    API设计规范---RESTful架构详解
    开源医学影像平台---Cornerstonejs开发指南
    开源医学影像平台---Cornerstonejs学习笔记<5>
  • 原文地址:https://www.cnblogs.com/Kanoon/p/13657901.html
Copyright © 2020-2023  润新知