ZZJC 2024 autumn Team Contest - 11题解

链接:https://codeforces.com/group/sqkBGLC2jv/contest/567721

A-解题思路

(800)按照题意模拟即可

A-代码实现

for _ in range(int(input())):
    n = list(map(int, list(input())))
    if sum(n[:3]) * 2 == sum(n):
        print("YES")
    else:
        print("NO")

B-解题思路

(800)范围很小,暴力枚举即可

B-代码实现

for _ in range(int(input())):
    n, m = map(int, input().split())
    s = []
    for i in range(n):
        s.append(input())
    ans = float("inf")
    for i in range(n):
        for j in range(n):
            t = float("inf")
            if i != j:
                t = 0
                for k in range(m):
                    t += min(ans, abs(ord(s[i][k]) - ord(s[j][k])))
            ans = min(ans, t)
    print(ans)

C-解题思路

(1100)要最少显然越大的越先吃,降序后前缀和预处理,二分取第一个大于x的位置即可

C-代码实现

#include <bits/stdc++.h>

int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);
    std::cout.tie(0);
    int t;
    std::cin >> t;
    while (t--) {
        int n ,q;
        std::cin >> n >> q;
        std::vector<int> a(n), pre(n + 1);
        for (int i = 0; i < n; i++) {
            std::cin >> a[i];
        }
        std::sort(a.begin(), a.end(), std::greater<int>());
        for (int i = 1; i <= n; i++) {
            pre[i] = pre[i - 1] + a[i - 1];
        }
        while (q--) {
            int x;
            std::cin >> x;
            auto pos = std::lower_bound(pre.begin(), pre.end(), x);
            if (pos != pre.end()) {
                std::cout << pos - pre.begin() << "\n";
            } else {
                std::cout << -1 << "\n";
            }
        }
    }
}

E-解题思路

(1300)先统计所有数字的数量,然后双指针扫描(注意这里的lr是值而非位置),t里面放的是出现次数大于等于k的数字,用于维护最大区间,也就是连续的值,某个具体值出现的次数大于k,看这个连续部分最多能有多长

E-代码实现

#include <bits/stdc++.h>

int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);
    std::cout.tie(0);
    int T;
    std::cin >> T;
    while (T--) {
        int n, k, l = 0, r = 0;
        std::cin >> n >> k;
        std::map<int, int> mp;
        std::vector<int> a(n), t;
        for (int i = 0; i < n; i++) {
            std::cin >> a[i];
            mp[a[i]]++;
        }
        for (auto [i, j]: mp) {
            if (j >= k) {
                if (t.empty() || i - 1 <= t.back()) {
                    t.push_back(i);
                } else {
                    if (!t.empty() && t.back() - t.front() >= r - l) {
                        l = t.front();
                        r = t.back();
                    }
                    t.clear();
                    t.push_back(i);
                }
            } else {
                if (!t.empty() && t.back() - t.front() >= r - l) {
                    l = t.front();
                    r = t.back();
                }
                t.clear();
            }
        }
        if (!t.empty() && t.back() - t.front() >= r - l) {
            l = t.front();
            r = t.back();
        }
        if (r) {
            std::cout << l << " " << r << "\n";
        } else {
            std::cout << -1 << "\n";
        }
    }
}

F-解题思路

(1300)dfs从根节点开始扫一遍并根据节点颜色对平衡值bal进行修改,某一部分的bal如果是0则说明这一部分是平衡的,直接对答案+1即可

F-代码实现

#include <bits/stdc++.h>

const int N = 4e3 + 10;
std::vector<int> g[N];
std::string s;

int dfs(int x, int &res) {
    int bal = (s[x - 1] == 'B') ? -1 : 1;
    for (int i : g[x]) {
        bal += dfs(i, res);
    }
    if (bal == 0) {
        res++;
    }
    return bal;
}

int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);
    std::cout.tie(0);
    int t;
    std::cin >> t;
    while (t--) {
        for (int i = 0; i < N; ++i) {
            g[i].clear();
        }
        int n;
        std::cin >> n;
        for (int i = 2; i <= n; i++) {
            int x;
            std::cin >> x;
            g[x].push_back(i);
        }
        std::cin >> s;
        int res = 0;
        dfs(1, res);
        std::cout << res << "\n";
    }
}

G-解题思路

(1700)这一题其实就是要找一个区间,让其中相同的数字尽可能的多,先记录这个数字的所有位置,然后滑动窗口扫描这个数字出现的位置并贪心即可

G-代码实现

#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, maxn = 0, ans = 0, ansl = 0, ansr = 0;
        std::cin >> n;
        std::map<int, std::vector<int>> mp;
        for (int i = 1; i <= n; i++) {
            int x;
            std::cin >> x;
            mp[x].push_back(i);
        }
        for (auto [x, v] : mp) {
            int l = 0, r = 0, len = 1, maxlen = 1, L = v[0], R = v[0];
            while (r + 1 < v.size()) {
                if (v[r + 1] - v[r] == 1) {  // 连续直接增加
                    len++;
                } else {
                    len -= (v[r + 1] - v[r] - 2);  // 不连续的时候需要减去的代价
                    if (len <= 0) {  // 如果代价太大则直接重置起点
                        len = 1;
                        l = r + 1;
                    }
                }
                r++;
                if (len > maxlen) {
                    maxlen = len;
                    L = v[l];
                    R = v[r];
                }
            }
            if (maxlen > maxn) {
                maxn = maxlen;
                ans = x;
                ansl = L;
                ansr = R;
            }
        }
        std::cout << ans << " " << ansl << " " << ansr << "\n";
    }
}

H-解题思路

(1400)题目的意思就是找一个区间,对区间内的每个数乘上2的索引次后还要是个升序区间,由于是一个连续区间,所以只需要看相邻的倍数关系就知道是否符合要求,统计范围内符合长度的区间数量即可

H-代码实现

for _ in range(int(input())):
    n, k = map(int, input().split())
    a = list(map(int, input().split()))
    ans = 0
    t = 1
    for i in range(1, n):
        if a[i - 1] < a[i] * 2:
            t += 1
        else:
            t = 1 
        if t >= k + 1:
            ans += 1
    print(ans)

I-解题思路

(1100)赤石题,模拟一下

I-代码实现

#include <bits/stdc++.h>

int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);
    std::cout.tie(0);
    int t;
    std::cin >> t;
    while (t--) {
        std::vector<int> time(4);
        std::set<int> ans;
        for (int i = 0; i < 4; i++) {
            char c;
            std::cin >> c;
            if (c == ':') {
                i--;
            } else {
                time[i] = c - '0';
            }
        }
        int x;
        std::cin >> x;
        for (int i = 0; i < 1440; i++) {  // 一天最多1440分钟,枚举一天的时间即可
            if (time[0] == time[3] && time[1] == time[2]) {
                ans.insert(time[0] * 1000 + time[1] * 100 + time[2] * 10 + time[3]);
            }
            time[3] += x;
            time[2] += time[3] / 10;
            time[3] = time[3] % 10;
            time[1] += time[2] / 6;
            time[2] = time[2] % 6;
            time[0] += time[1] / 10;
            time[1] = time[1] % 10;
            while (time[0] * 10 + time[1] >= 24) {
                time[0] -= 2;
                time[1] -= 4;
            }
        }
        std::cout << ans.size() << "\n";
    }
}
# 日历时间类的题目py也很有优势
from datetime import datetime, timedelta

for _ in range(int(input())):
    s, x = input().split()
    x = int(x)

    st = set()
    now = datetime.strptime(s, "%H:%M")

    for i in range(1440):
        S = now.strftime("%H:%M")
        if  S == S[::-1]:
            st.add(S)
        now += timedelta(minutes = x)
        if S == s:
            break

    print(len(st))

J-解题思路

(1200)前缀和预处理后二分要删除的位置,枚举左端点即可

J-代码实现

#include <bits/stdc++.h>

int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);
    std::cout.tie(0);
    int t;
    std::cin >> t;
    while (t--) {
        int n, s, ans = 1e9;
        std::cin >> n >> s;
        std::vector<int> a(n + 1), pre(n + 1);
        for (int i = 1; i <= n; i++) {
            std::cin >> a[i];
            pre[i] = pre[i - 1] + a[i];
        }
        for (int i = 1; i <= n; i++) {
            int l = i, r = n;
            while (l <= r) {
                int mid = (l + r) / 2;
                if (pre[mid] - pre[i - 1] <= s) {
                    l = mid + 1;
                } else {
                    r = mid - 1;
                }
            }
            if (pre[r] - pre[i - 1] == s) {
                ans = std::min(ans, n - (r - i + 1));
            }
        }
        if (ans != 1e9) {
            std::cout << ans << "\n";
        } else {
            std::cout << -1 << "\n";
        }
    }
}
posted @ 2024-11-20 23:52  udiandianis  阅读(38)  评论(0)    收藏  举报