Ethflow Round 1 (Codeforces Round 1001, Div. 1 + Div. 2)

A. String

题目大意

给你一个01串,每次操作可以选择一个相邻字符不一样的子串进行01翻转,问全变成0至少要操作几次

解题思路

显然只要看字符串中有多少个1,每次选择1进行翻转即可

代码实现

#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);

    int t;
    std::cin >> t;

    while (t--) {
        std::string s;
        std::cin >> s;

        std::cout << std::count(s.begin(), s.end(), '1') << "\n";
    }
}

B. Clockwork

题目大意

给你一个数组,其中每个的数字每秒会-1,你可以选择一个初始位置,此后每次可以选择去往任意一个相邻的位置,让你所在的位置可以让数字回到初始值,问无限时间下能否让所有位置都不为零

解题思路

要稳定地维护一个位置其实最坏就是左边往返一次或者右边往返一次,因此只需要考虑这两个方向的距离和当前位置的数字大小即可

代码实现

#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);

    int t;
    std::cin >> t;

    while (t--) {
        int n, f = 1;
        std::cin >> n;

        std::vector<int> a(n + 1);
        for (int i = 1; i <= n; i++) {
            std::cin >> a[i];
            if (2 * std::max(i - 1, n - i) >= a[i]) {
                f = 0;
            }
        }

        if (f) {
            std::cout << "YES\n";
        } else {
            std::cout << "NO\n";
        }
    }
}

C. Cirno and Operations

题目大意

给你一个数组,每次你可以选择将数组翻转,或者用这个数组的差分数组代替它,不限操作次数,问数组求和的最大值是多少

解题思路

显然每次差分替代的方式会让数组长度减少1,而翻转则是为了让下一次差分数组得到尽可能大的正数来加。而翻转后差分求和得到的正数,其实就是正序差分求和得到的负数的相反数,因此无需考虑翻转与否,只需要不断用差分数组替代,对和的绝对值取大即可

代码实现

#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);

    int t;
    std::cin >> t;

    while (t--) {
        int n;
        std::cin >> n;

        std::vector<i64> a(n);
        for (int i = 0; i < n; i++) {
            std::cin >> a[i];
        }

        i64 ans = std::accumulate(a.begin(), a.end(), 0ll);
        while (--n) {
            std::vector<i64> b(n);
            for (int i = 0; i < n; i++) {
                b[i] = a[i + 1] - a[i];
            }
            ans = std::max(ans, std::abs(std::accumulate(b.begin(), b.end(), 0ll)));
            a = b;
        }

        std::cout << ans << "\n";
    }
}

D. Balanced Tree

题目大意

给你一棵树,并给定节点的权值范围,可以在范围中任意选择,此后你可以选择两点uv,将以u为根的v的子树的节点权值全部+1,问让所有节点的权值都相同的最小权值是多少

解题思路

假设1是树的根,并且已经知道了各个节点的值,那么对于连接x和fa(x)节点的边,要让x和fa(x)相等,显然只有将他们变成uv的时候才会更改,执行二者差值那么多次后,可以让这两个节点相等,对所有的边都进行这样的操作,整棵树的点就都相等了。可以自下而上地传递这个差值,即x比fa(x)大的时候需要调整的大小,最终的答案就是根节点初始值与传递过来的总差值之和,即ans=a1+u1max(auafa(u),0)

代码实现

#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);

    int t;
    std::cin >> t;

    while (t--) {
        int n;
        std::cin >> n;

        std::vector<int> l(n + 1), r(n + 1), a(n + 1);
        for (int i = 1; i <= n; i++) {
            std::cin >> l[i] >> r[i];
        }

        std::vector<std::vector<int>> g(n + 1);
        for (int i = 1; i < n; i++) {
            int u, v;
            std::cin >> u >> v;
            g[u].push_back(v);
            g[v].push_back(u);
        }

        i64 ans = 0;
        auto dfs = [&](auto&& self, int u, int fa) -> void {
            int maxn = l[u];
            for (auto v : g[u]) {
                if (v == fa) {
                    continue;
                }
                self(self, v, u);
                maxn = std::max(maxn, a[v]);
            }
            a[u] = std::min(maxn, r[u]);
            for (auto v : g[u]) {
                if (v != fa) {
                    ans += std::max(0, a[v] - a[u]);
                }
            }
        };

        dfs(dfs, 1, -1);

        std::cout << ans + a[1] << "\n";
    }
}
posted @   udiandianis  阅读(47)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
  1. 1 山海不可平 CMJ
山海不可平 - CMJ
00:00 / 00:00
An audio error has occurred.

纯音乐,请欣赏

点击右上角即可分享
微信分享提示