1 条题解

  • 0
    @ 2026-4-5 21:56:09

    F1. 完成所有项目(简单版本)

    问题重述

    Polycarp 当前评分为 rr。有 nn 个项目,第 ii 个项目需要评分至少 aia_i 才能开始,完成后评分变化为 bib_i(可正可负)。评分在任何时候不能低于 00
    问:是否存在一种顺序,使得所有项目都能完成?

    • n100n \le 100r30000r \le 30000
    • ai30000a_i \le 30000300bi300-300 \le b_i \le 300

    核心思路

    将项目分为两类:

    • 加分项目bi0b_i \ge 0
    • 减分项目bi<0b_i < 0

    第一步:处理加分项目

    对于 bi0b_i \ge 0 的项目,显然应该按照 aia_i 从小到大排序(先做要求低的,再做要求高的)。
    依次检查当前评分是否 ai\ge a_i,若是则完成并更新 r=r+bir = r + b_i;否则直接输出 "NO"

    第二步:处理减分项目

    对于 bi<0b_i < 0 的项目,情况更复杂。
    关键观察:完成一个减分项目后评分会下降,所以需要合理安排顺序


    减分项目的贪心策略

    引理

    将所有减分项目按 (ai+bi)(a_i + b_i) 从大到小排序,然后依次尝试完成,是最优的。

    证明思路(交换论证)

    考虑两个相邻的减分项目 iijjbi,bj<0b_i, b_j < 0)。
    假设当前评分为 rr,先做 ii 再做 jj 可行的条件是:

    rai,r+biajr \ge a_i,\quad r + b_i \ge a_j

    先做 jj 再做 ii 可行的条件是:

    raj,r+bjair \ge a_j,\quad r + b_j \ge a_i

    我们希望选择约束更弱的顺序。比较两个条件中的关键项:

    • iijj 要求 rmax(ai,ajbi)r \ge \max(a_i, a_j - b_i)
    • jjii 要求 rmax(aj,aibj)r \ge \max(a_j, a_i - b_j)

    注意到 ajbi>aja_j - b_i > a_jaibj>aia_i - b_j > a_i,所以只需比较 ajbia_j - b_iaibja_i - b_j

    计算:

    $$(a_j - b_i) < (a_i - b_j) \iff a_j + b_j < a_i + b_i $$

    因此,当 ai+bi>aj+bja_i + b_i > a_j + b_j 时,先做 iijj 的条件更弱(更容易满足)。
    所以应该按 ai+bia_i + b_i 从大到小排序。


    处理边界条件

    对于减分项目,还有一个细节:
    为了保证完成项目后评分非负,在尝试完成前需要额外检查:

    rmax(ai,bi)r \ge \max(a_i, -b_i)

    因为如果 rbir \ge -b_i,则完成后的评分 r+bi0r + b_i \ge 0
    所以实际操作中,可将 aia_i 更新为 max(ai,bi)\max(a_i, -b_i),再按 ai+bia_i + b_i 排序。


    算法步骤

    1. 读入 n,rn, r
    2. 将项目分为两组:
      • posbi0b_i \ge 0,按 aia_i 升序排序
      • negbi<0b_i < 0,按 (ai+bi)(a_i + b_i) 降序排序(或按 aia_i 升序?需注意)
    3. 处理 pos 组:依次判断 rair \ge a_i,更新 r=r+bir = r + b_i
    4. 处理 neg 组:依次判断 rair \ge a_ir+bi0r + b_i \ge 0,更新 r=r+bir = r + b_i
    5. 若所有项目都完成,输出 "YES",否则 "NO"

    时间复杂度

    排序 O(nlogn)O(n \log n),遍历 O(n)O(n),总体 O(nlogn)O(n \log n)


    示例解析

    示例 1

    3 4
    4 6
    10 -2
    8 -1
    
    • 加分项目:(4,6),按 aa 排序后唯一,r=44r=4 \ge 4r=10r=10
    • 减分项目:(10,-2), (8,-1)
      计算 a+ba+b102=810-2=881=78-1=7,按降序:先 (10,-2)(8,-1)
      当前 r=10r=10:完成 (10,-2)r=8r=8
      完成 (8,-1)r=7r=7
      全部完成 → "YES"

    标程代码(C++)

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
        int n, r;
        cin >> n >> r;
        
        vector<pair<int, int>> pos, neg;
        for (int i = 0; i < n; ++i) {
            int a, b;
            cin >> a >> b;
            if (b >= 0) {
                pos.push_back({a, b});
            } else {
                neg.push_back({a, b});
            }
        }
        
        // 处理加分项目
        sort(pos.begin(), pos.end());
        for (auto &p : pos) {
            if (r < p.first) {
                cout << "NO" << endl;
                return 0;
            }
            r += p.second;
        }
        
        // 处理减分项目:按 a+b 降序排序
        sort(neg.begin(), neg.end(), [](pair<int, int> x, pair<int, int> y) {
            return x.first + x.second > y.first + y.second;
        });
        
        for (auto &p : neg) {
            if (r < p.first) {
                cout << "NO" << endl;
                return 0;
            }
            r += p.second;
            if (r < 0) {
                cout << "NO" << endl;
                return 0;
            }
        }
        
        cout << "YES" << endl;
        return 0;
    }
    

    易错点

    1. 减分项目的排序依据ai+bia_i + b_i 降序,不是 aia_i 升序
    2. 完成减分项目后要检查 rr 是否 0\ge 0
    3. aia_i 可能小于 bi-b_i,此时实际要求是 rbir \ge -b_i(但标程中直接用 aia_i 判断,因为 aia_i 已经保证了这一点?需要确认)
    • 1

    信息

    ID
    6422
    时间
    1000ms
    内存
    256MiB
    难度
    8
    标签
    递交数
    1
    已通过
    1
    上传者