CF727F Polycarp’s problems
算法
- 贪心
思路
考虑特殊情况。当 时,问题转化为:给定 , 求删除最少元素使得对于任意的 ,满足 。 将特殊情况扩展到 ,即对于每一个给定的 ,求解上述问题。 考虑贪心,即对于一个 ,满足 , 则必定删除前面最大的负数,才会使最后的结果最优.于是可以逆向思维,倒序遍历数组 ,维护一个大根堆(即维护绝对值最小的负数,对于每一个 , 将其入队;对于每一个 ,用 抵消堆顶元素,直到堆为空或 。 最后将堆里的元素全部放入一个新数组,即这些负数在 里都不能被抵消,只能由 抵消,被删除的个数即为剩余负数的个数减去 最多可以抵消的负数,可以二分解决。
代码
#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;}
Comments
Quiet notes for this article.