• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
jacklee404
Never Stop!
博客园    首页    新随笔    联系   管理    订阅  订阅
CF1779-Least Prefix Sum

Least Prefix Sum

C. Least Prefix Sum

思路 (贪心 + 优先队列)

设\(p_i = \sum\limits_{i=1}^n a_i\),设x,\(p_x < p_m\), 且\(1 \le x < m\), 则\(p_x - p_m\) 为两者的大小关系,显然若满足该关系应该保证\(\sum\limits_{i=x+1}^m a_i \le 0\), 我们采取贪心的策略每次挑选一个区间\([x+1, m]\)的最大值,当且仅当\(p_x - p_m \le 0\)时,所需要的操作数最少,因为\(p_m\)的值非递增,我们保证该策略为最优策略, 对于\(m < x \le n\) 同理。

复杂\(O(nlogn)\)

Code

#include <iostream>
#include <vector>
#include <queue>
#define rep(i, j, n) for (int i = j; i <= n; i ++)
#define per(i, j, n) for (int i = j; i >= n; i --)
using namespace std;

void solve() {
	int n, m, ans = 0; cin >> n >> m;
	vector<long long> a(n + 1), pre(n + 1, 0);
	for (int i = 1; i <= n; i ++) {
		cin >> a[i];
		pre[i] = pre[i - 1] + a[i];
	}
	
	priority_queue<long long> h;
	long long curr = 0;
	per (i, m, 2) {
		if (a[i] > 0) h.push(a[i]);
		curr += a[i];
		while (curr > 0) {
			int x = h.top(); h.pop();
			curr -= 2 * x, ans ++;
		}
	}
	while (h.size()) h.pop();
	curr = 0;
	rep (i, m + 1, n) {
		if (a[i] < 0) h.push(-a[i]);
		curr += a[i];
		while (curr < 0) {
			int x = h.top(); h.pop();
			curr += 2 * x;
			++ ans;
		}
	}
	cout << ans << "\n";
}

int main() {
	int _; cin >> _;
	while (_ --) {
		solve();
	}
}
posted on 2023-01-04 15:18  Jack404  阅读(26)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3