题解:CF727F Polycarp's problems

link

贪心做法。


本题贪心做法的实质就是用整数尽量多地抵消该整数后面的负数。

如果正着做,没有办法考虑全该数后面的所有负数,所以倒着做。

例如当前遍历到了 50,此时序列如下:

,50,50,10,20

易得我们 50 应该抵消的是 10,20,而不是前面的 50,因为我们要使删除的数越少越好。

但是剩下的 501020=20 也不能空着,抵消一部分的剩下的 50 即可。

最终得到:

,30

发现上述操作可以用堆来维护,具体维护方法见代码。


  • 时间复杂度:O((n+m)logn),瓶颈在于堆和二分。
  • 空间复杂度:略。

代码:

// 加强版:n,m <= 1000000 代码
#include <bits/stdc++.h>
#define int long long
#define pii pair<int, int>
using namespace std;

const int N = 1e6 + 5;

int n, m, a[N], b[N], tot;

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	priority_queue<int> q;
	for (int i = n; i >= 1; i--) {
		if (a[i] < 0) {
			q.push(a[i]);
		} else {
			while (q.size() && a[i] >= 0) {
				a[i] += q.top();
				q.pop();
			}
			if (a[i] < 0) {
				q.push(a[i]);
			}
		}
	}
	while (q.size()) {
		b[++tot] = -q.top();
		q.pop();
	}
	for (int i = 1; i <= tot; i++) {
		b[i] += b[i - 1];
	}
	for (int i = 1; i <= m; i++) {
		int x;
		cin >> x;
		if (x >= b[tot]) {
			cout << "0\n";
			continue;
		}
		int t = upper_bound(b + 1, b + tot, x) - b - 1;
		cout << tot - t << "\n";
	}
	return 0;
}
posted @   Archippus  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示