CodeForces 727F

VJudge 洛谷 Codeforces

算法

  • 贪心

思路

考虑特殊情况。当 \(m=1\) 时,问题转化为:给定 \(a_0\), 求删除最少元素使得对于任意的 \(i\),满足 \(\Sigma_{j=0}^{i} a_{j} \ge 0\)
将特殊情况扩展到 \(m \le 10^6\),即对于每一个给定的 \(a_0\),求解上述问题。
考虑贪心,即对于一个 \(i\),满足 \(\Sigma_{j=0}^{i} a_{j} < 0\), 则必定删除前面最大的负数,才会使最后的结果最优.于是可以逆向思维,倒序遍历数组 \(a\),维护一个大根堆(即维护绝对值最小的负数,对于每一个 \(a_{i} < 0\), 将其入队;对于每一个 \(a_{i} \ge 0\),用 \(a_{i}\) 抵消堆顶元素,直到堆为空或 \(a_{i} < 0\)
最后将堆里的元素全部放入一个新数组,即这些负数在 \(a_{1} \to a_{n}\) 里都不能被抵消,只能由 \(a_{0}\) 抵消,被删除的个数即为剩余负数的个数减去 \(a_{0}\) 最多可以抵消的负数,可以二分解决。

代码

#include <bits/stdc++.h>
#define OnlineJudge
  
using namespace std;
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  
  int n, m;
  cin >> n >> m;
  
  vector<long long> a(n), b(m);

  for (int i = 0; i < n; i++) {
    cin >> a[i];
  }

  priority_queue<long long, vector<long long>, less<long long>> q;

  for (int i = n - 1; i >= 0; i--) {
    if (a[i] < 0) {
      q.emplace(a[i]);
    } else {
      while (!q.empty() && a[i] >= 0) {
        a[i] += q.top();
        q.pop();
      }
      
      if (a[i] < 0) {
        q.emplace(a[i]);
      }
    }
    continue;
  }
  
  vector<long long> modify;
  
  while (!q.empty()) {
    modify.emplace_back(-q.top());
    q.pop();
  }

  // reverse(modify.begin(), modify.end());

  for (int i = 1; i < static_cast<int>(modify.size()); i++) {
    modify[i] = modify[i] + modify[i - 1];
  }

  #ifndef OnlineJudge
  for (auto&& var : modify) {
    cout << var << " ";
  }
  cout << "\n";
  #endif

  for (int i = 0; i < m; i++) {
    cin >> b[i];

    int answer;
    if (modify.empty() || modify.back() <= b[i]) {
      answer = 0;
    } else {
      int pos = upper_bound(modify.begin(), modify.end(), b[i]) - modify.begin();
      answer = static_cast<int>(modify.size()) - pos;
    }

    cout << answer << '\n';
  }

  return 0;
}
posted @ 2025-07-09 12:14  Fallen_Leaf  阅读(19)  评论(0)    收藏  举报