CF2055B. Crafting 题解 简单贪心

题目链接:https://codeforces.com/contest/2055/problem/B

解题思路:

首先,如果存在至少两个 \(a_i \lt b_i\),就面临一个局面,就是:

我不够问你要,然后你也不够问我要。

此时,如果我借给你那么更不够了,你借给我你就不够了。

所以如果至少存在两个下标 \(i\) 满足 \(a_i \lt b_i\),肯定是 NO

如果所有的下标 \(i\) 都满足 \(a_i \ge b_i\),肯定是 YES

如果恰好有一个下标 \(i\) 满足 \(a_i \lt b_i\),其他下标 \(j\)\(1 \le j \le n, j \neq i\))均满足 \(a_j \ge b_j\)

\(a_i\) 至少需要加 \(b_i - a_i\)\(1\)

其他 \(a_j\)\(j \neq i\))最多减 \(\min\limits_{j \neq i} a_j - b_j\)\(1\)

所以此时,若 \(b_i - a_i \le \min\limits_{j \neq i} a_j - b_j\),则答案为 YES;否则,答案为 NO

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;

int T, n, a[maxn], b[maxn];

bool check() {
    int p, cnt = 0, m = 1e9; // p 对应 a[p] < b[p] 的下标 p,cnt 表示有多少个 a[i] < b[i]
    for (int i = 1; i <= n; i++) {
        if (a[i] < b[i]) {
            p = i;
            cnt++;
            if (cnt > 1)
                return false;
        }
        else { // a[i] >= b[i]
            m = min(m, a[i] - b[i]);
        }
    }
    if (cnt == 0)
        return true;
    // cnt == 1
    return b[p] - a[p] <= m;
}

int main() {
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%d", a+i);
        for (int i = 1; i <= n; i++) scanf("%d", b+i);
        puts(check() ? "YES" : "NO");
    }
    return 0;
}
posted @ 2025-01-13 03:47  quanjun  阅读(99)  评论(0)    收藏  举报