ICPC 2024 杭州站

A. AUS

题目大意

给你三个字符串S1、S2、S3,问是否存在一种字母映射方式使得F(S1)等于F(S2)但是不等于F(S3)

解题思路

想要让S1、S2相等首先显然要满足长度相等,因此可以先把长度不相等的时候的存在关系判断出来,对于三个字符串长度都相等的情况,可以通过遍历修改字符串让S1变成S2,或者S2变成S1,逐字符比较不相等修改即可,可直接使用Python的replace完成替换,注意要提前把字符取出来,因为replace后字符串已经发生变化,最后只需要查看是不是满足题目要求即可

代码实现

for _ in range(int(input())):
    s1 = input()
    s2 = input()
    s3 = input()
    
    if len(s1) != len(s2):
        print("NO")
    elif len(s1) != len(s3):
        print("YES")
    else:
        S1 = [s1, s1]
        S2 = [s2, s2]
        S3 = [s3, s3]
        for i in range(len(s1)):
            A, B = S1[0][i], S2[0][i]
            if A != B:
                S1[0] = S1[0].replace(B, A)
                S2[0] = S2[0].replace(B, A)
                S3[0] = S3[0].replace(B, A)
            
            A, B = S1[1][i],  S2[1][i]
            if A != B:
                S1[1] = S1[1].replace(A, B)
                S2[1] = S2[1].replace(A, B)
                S3[1] = S3[1].replace(A, B)

        if S1[0] == S2[0] and S1[0] != S3[0] or S1[1] == S2[1] and S1[1] != S3[1]:
            print("YES")
        else:
            print("NO")

K. Kind of Bingo

题目大意

给你一个n * m的网格,再给你一个排列表示标记的顺序,问修改操作顺序后让一行网格被标记最少要操作多少次

解题思路

根据给出的这个数值大小即可得知当前正在标记哪一行,允许修改k次则保证至少能把k个靠后的操作放到前面来,因此只需要找到第一个满足已经操作m - k次(至少得是0)的是哪一行,再对这一行改变操作即可,注意最后的答案要和m取大,即至少操作m次才能填充m个

代码实现

#include <bits/stdc++.h>

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, m, k, ok = -1;
        std::cin >> n >> m >> k;

        std::vector<int> p(n * m), f(n);
        for (int i = 0; i < n * m; i++) {
            std::cin >> p[i];
            int x = (p[i] - 1) / m;
            f[x]++;
            if (ok == -1 && f[x] >= std::max(0, m - k)) {
                ok = x;
            }
        }

        std::vector<int> ans;
        for (int i = 0; i < n * m; i++) {
            int x = (p[i] - 1) / m;
            if (x == ok) {
                ans.push_back(i + 1);
            }
        }

        std::cout << std::max(m, ans[std::max(0, m - k - 1)]) << "\n";
    }
}

E. Elevator II

题目大意

有一部电梯每次只能乘坐1人,上升消耗r - l,下降无消耗,问把所有人送到目的地的最小消耗之和并给出安排方案

解题思路

先让电梯升到最高处,上升过程中的人能送就送(他们都是去往最高处途中顺手的事),然后按照r降序送,这样保证了当前这个r不会再来,不会有浪费,途中记录一下乘客在原序列的中的位置最后输出即可

代码实现

#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;
        std::cin >> n >> f;

        std::vector<std::array<int, 3>> lr(n);
        for (int i = 0; i < n; i++) {
            std::cin >> lr[i][0] >> lr[i][1];
            lr[i][2] = i + 1;
        }

        std::sort(lr.begin(), lr.end());

        i64 ans = 0;
        std::vector<int> ord, F(n);
        for (int i = 0; i < n; i++) {
            auto [l, r, idx] = lr[i];
            if (l < f) {
                if (r > f) {
                    f = r;
                    ans += r - l;
                    ord.push_back(idx);
                    F[idx - 1] = 1;
                }
                continue;
            }
            if (l > f) {
                ans += l - f;
            }
            f = r;
            ans += r - l;
            ord.push_back(idx);
            F[idx - 1] = 1;
        }

        std::sort(lr.begin(), lr.end(), [&](std::array<int, 3> a, std::array<int, 3> b) { return a[0] > b[0]; });

        for (int i = 0; i < n; i++) {
            auto [l, r, idx] = lr[i];
            if (F[idx - 1]) {
                continue;
            }
            f = r;
            ans += r - l;
            ord.push_back(idx);
            F[idx - 1] = 1;
        }

        std::cout << ans << "\n";
        for (int i = 0; i < n; i++) {
            std::cout << ord[i] << " \n"[i == n - 1];
        }
    }
}

H. Heavy-light Decomposition

题目大意

给你几条链,问能否构造出一棵树,让它HLD的结果是这几条链

解题思路

乱搞一下发现不可能的情况有两种,链的长度全相等或者至少有两条最长链,链的长度极差是1(证明)。
剩下的情况里,如果只有一条链直接输出即可;如果最长链只有一条,其他链挂最长链第一个节点即可;如果有多条最长链,最短链挂最长链第二个节点,其余链挂最长链第一个节点即可

代码实现

#include <bits/stdc++.h>

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, k, maxn = 0, minn = 1e9, cnt = 0, idx = -1;
        std::cin >> n >> k;

        std::vector<int> len(k);
        std::vector<std::array<int, 2>> lr(k);
        for (int i = 0; i < k; i++) {
            std::cin >> lr[i][0] >> lr[i][1];

            len[i] = lr[i][1] - lr[i][0] + 1;
            if (len[i] > maxn) {
                idx = i;
            }
            if (maxn == len[i]) {
                cnt++;
            } else if (maxn < len[i]) {
                maxn = len[i];
                cnt = 1;
            }
            minn = std::min(minn, len[i]);
        }
        if (maxn == minn && k >= 2 || maxn - minn == 1 && cnt >= 2) {
            std::cout << "IMPOSSIBLE\n";
        } else {
            std::vector<int> ans(n + 1);
            if (cnt == 1) {
                for (auto [l, r] : lr) {
                    ans[l] = lr[idx][0];
                    for (int i = l + 1; i <= r; i++) {
                        ans[i] = i - 1;
                    }
                }
                ans[lr[idx][0]] = 0;
            } else {
                ans[lr[idx][0]] = 0;
                for (int i = lr[idx][0] + 1; i <= lr[idx][1]; i++) {
                    ans[i] = i - 1;
                }
                for (int i = 0; i < k; i++) {
                    if (i != idx) {
                        if (len[i] != minn) {
                            ans[lr[i][0]] = lr[idx][0];
                            for (int j = lr[i][0] + 1; j <= lr[i][1]; j++) {
                                ans[j] = j - 1;
                            }
                        } else {
                            ans[lr[i][0]] = lr[idx][0] + 1;
                            for (int j = lr[i][0] + 1; j <= lr[i][1]; j++) {
                                ans[j] = j - 1;
                            }
                        }
                    }
                }
            }

            for (int i = 1; i <= n; i++) {
                std::cout << ans[i] << " \n"[i == n];
            }
        }
    }
}

M. Make It Divisible

题目大意

给你一个数组,问每个数都加上x后满足所有相邻数字存在整数倍关系的x有多少个并求和

解题思路

先用单调栈找到所有bi和它两侧第一个比它大的数构成多个AB数对,接下来挑选x让所有AB数对成为倍数关系,只需要枚举任意一个数对差值的fac,找出构成所有数对都为倍数关系的fac统计即可

代码实现

#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--) {
        i64 n, k;
        std::cin >> n >> k;

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

        std::stack<int> stk;
        std::vector<std::array<int, 2>> P;
        for (int i = 0; i < n; i++) {
            while (!stk.empty() && b[stk.top()] >= b[i]) {
                if (b[stk.top()] > b[i]) {
                    P.push_back({b[i], b[stk.top()]});
                }
                stk.pop();
            }
            stk.push(i);
        }
        while (!stk.empty()) {
            stk.pop();
        };
        for (int i = n - 1; i >= 0; i--) {
            while (!stk.empty() && b[stk.top()] >= b[i]) {
                if (b[stk.top()] > b[i]) {
                    P.push_back({b[i], b[stk.top()]});
                }
                stk.pop();
            }
            stk.push(i);
        }

        if (P.empty()) {
            std::cout << k << " " << k * (k + 1) / 2 << "\n";
            continue;
        }

        std::vector<int> X;
        int A = P[0][1] - P[0][0];
        for (int i = 1; i * i <= A && i <= k + P[0][0]; i++) {
            if (A % i == 0) {
                if (i > P[0][0]) {
                    X.push_back(i - P[0][0]);
                }
                if (A / i > i && A / i <= k + P[0][0] && A / i > P[0][0]) {
                    X.push_back(A / i - P[0][0]);
                }
            }
        }

        std::vector<int> ans;
        for (auto x : X) {
            int f = 1;
            for (auto [A, B] : P) {
                if ((B + x) % (A + x) != 0) {
                    f = 0;
                    break;
                }
            }
            if (f) {
                ans.push_back(x);
            }
        }

        std::cout << ans.size() << " " << std::accumulate(ans.begin(), ans.end(), 0ll) << "\n";
    }
}
posted @   udiandianis  阅读(69)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
  1. 1 山海不可平 CMJ
山海不可平 - CMJ
00:00 / 00:00
An audio error has occurred.

纯音乐,请欣赏

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