Codeforces Round 1002 (Div. 2)

A. Milya and Two Arrays

题目大意

给你两个数组ab,数组中的元素都至少出现了两次,现在你可以重排a数组,问能否让 ai+bi 出现三个不同的数字

解题思路

显然两个数组每个数组各有两种不同的元素及以上或者其中一个数组本身有至少三种便可以构造出,因此统计一下两个数组里不同的元素各自有多少即可

代码实现

#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> a(n);
        std::map<int, int> mpa;
        for (int i = 0; i < n; i++) {
            std::cin >> a[i];
            mpa[a[i]]++;
        }

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

        if (mpa.size() + mpb.size() > 3) {
            std::cout << "YES\n";
        } else {
            std::cout << "NO\n";
        }
    }
}

B. Cost of the Array

题目大意

给你一个数组a,要求把他划分为k个连续子数组,然后将偶数位置的子数组重新拼接为一个新数组b,问让 bi+1i 的最小i是多少

解题思路

首先需要对于k的大小简单讨论一下,如果k == n,则根本无法划分出其他情况,按照题意模拟即可;如果不相等,要让答案尽可能小只需要尽早和索引不匹配即可,因此只需要看在最前面能不能找到1,最坏的情况一直能找到1导致是后面为k - 1个子数组长度是1,所以检查1 ~ n - k + 1的位置即可,有一个位置不是1,以此为开头即可得到答案是1,否则前面全都是1,只需要让两个1连起来即可得到答案2

代码实现

#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, k, f = 1;
        std::cin >> n >> k;
        std::vector<int> a(n);
        for (int i = 0; i < n; i++) {
            std::cin >> a[i];
        }

        if (k == n) {
            for (int i = 1; i < n; i += 2) {
                if (a[i] != (i + 1) / 2) {
                    std::cout << (i + 1) / 2 << "\n";
                    f = 0;
                    break;
                }
            }
            if (f) {
                std::cout << k / 2 + 1 << '\n';
            }
        } else {
            for (int i = 1; i <= n - k + 1; i++) {
                if (a[i] != 1) {
                    std::cout << "1\n";
                    f = 0;
                    break;
                }
            }
            if (f) {
                std::cout << "2\n";
            }
        }
    }
}

C. Customer Service

题目大意

给你n * n的一个矩阵,每次取后缀长度为i的一个数组,问mex最大是多少

解题思路

只需要枚举后缀长度,暴力查询有多少行满足当前mex,对下一轮的数量进行一个简单的约束直到不再有任何一行满足即可(由于mex是连续的,其实只需要检查每一行连续的后缀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<std::vector<int>> a(n, std::vector<int>(n));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                std::cin >> a[i][j];
            }
        }

        std::vector<std::vector<int>> suff(n + 1, std::vector<int>(n + 1));
        for (int i = 0; i < n; i++) {
            for (int j = n - 1; j >= 0; j--) {
                suff[i][j] = suff[i][j + 1] + a[i][j];
            }
        }

        int ans = 1, p = n - 1;
        for (int j = n - 1; j >= 0; j--) {
            int cnt = 0;
            for (int i = 0; i < n; i++) {
                cnt += ans == suff[i][j];
            }
            cnt = std::min(cnt, p);

            if (cnt) {
                ans += 1;
                p = cnt - 1;
            }
        }

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

D. Graph and Graph

题目大意

给你两张图,点数相同边数不一定相同并给定起点,每次必须由当前节点向相邻节点移动一步,代价为两图新节点编号差值的绝对值,问执行无数次操作的最小代价是多少,无穷则输出-1(就是问当g1执行从点u到v时,g2也执行从点u到v,进入这个状态的最小代价,此后只需要在uv不断来回移动即可,代价都是0)

解题思路

首先预处理一下两图点和边之间的关系,标记两图都联通的节点,注意“所有测试用例的 n 、 m1 和 m2 之和不超过 1000”,因此我们可以 n3 暴力的预处理,此后使用dij维护每一个在同一步执行的点对代价,对于相同的点且可以去同一个节点的点代价取小即可

代码实现

#include <bits/stdc++.h>

using i64 = long long;
const i64 INF = 4e18;

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, s1, s2, m1, m2;
        std::cin >> n >> s1 >> s2 >> m1;

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

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

        std::vector<int> ok(n + 1);
        for (int i = 1; i <= n; i++) {
            for (int j : g1[i]) {
                for (int k : g2[i]) {
                    if (j == k) {
                        ok[i] = 1;
                    }
                }
            }
        }

        std::vector<std::vector<i64>> dist(n + 1, std::vector(n + 1, INF));
        dist[s1][s2] = 0;
        std::priority_queue<std::array<i64, 3>> pq;
        pq.push({0, s1, s2});
        i64 ans = INF;
        while (!pq.empty()) {
            auto [_, x, y] = pq.top();
            pq.pop();

            if (x == y && ok[x]) {
                ans = std::min(ans, dist[x][y]);
            }

            for (auto i : g1[x]) {
                for (auto j : g2[y]) {
                    if (dist[i][j] > dist[x][y] + abs(i - j)) {
                        dist[i][j] = dist[x][y] + abs(i - j);
                        pq.push({-dist[i][j], i, j});
                    }
                }
            }
        }

        if (ans == INF) {
            ans = -1;
        }

        std::cout << ans << "\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.

纯音乐,请欣赏

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