题目 | Least Prefix Sum
Hello 2023
C. Least Prefix Sum
https://codeforces.com/contest/1779/problem/C
2 seconds / 256 megabytes
standard input / standard output
Problem
Baltic, a famous chess player who is also a mathematician, has an array
- Choose some index
( ); - multiply
with , that is, set .
Baltic's favorite number is , and he wants to be the smallest of all non-empty prefix sums. More formally, for each it should hold that
Please note that multiple smallest prefix sums may exist and that it is only required that
Help Baltic find the minimum number of operations required to make
Input
Each test contains multiple test cases. The first line contains the number of test cases
The first line of each test case contains two integers
The second line contains
It is guaranteed that the sum of
Output
For each test case, print a single integer — the minimum number of required operations.
Example
Input
6
4 3
-1 -2 -3 -4
4 3
1 2 3 4
1 1
1
5 5
-2 3 -5 1 -20
5 2
-2 3 -5 -5 -20
10 4
345875723 -48 384678321 -375635768 -35867853 -35863586 -358683842 -81725678 38576 -357865873
Output
1
1
0
0
3
4
Note
In the first example, we perform the operation
In the second example, we perform the operation
In the third and fourth examples,
In the fifth example, a valid sequence of operations is:
, , .
The array becomes
题解
题意
给定一个序列
思路
对下标
下图为前缀和的折线图,我们对
可以看到变化是
这个结论的作用是,我们对下标
对
对
如下图,我们对
并且,
由于我们要操作次数最小,根据贪心,我们肯定选的是当前的最值进行操作。(这点非常重要,我就是因为比赛时一直没想到这点,一直陷入错误的思维。没做出来这题的人很多都是这点漏掉了)
对于
从
由于
对于
从
由于
最大最小值的维护方法
使用 STL 优先队列即可实现
代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int MAXN = 2e5 + 10;
int n, m;
int a[MAXN], ps[MAXN];
void solve()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
ps[i] = ps[i - 1] + a[i];
int psm = ps[m], cnt = 0, offset = 0;
priority_queue<int> big_heap;
for (int i = m; i >= 1; i--)
{
while (ps[i] < psm + offset)
{
cnt++;
offset -= big_heap.top() * 2;
big_heap.pop();
}
if (a[i] > 0)
big_heap.push(a[i]);
}
priority_queue<int, vector<int>, greater<int>> small_heap;
offset = 0;
for (int i = m + 1; i <= n; i++)
{
if (a[i] < 0)
small_heap.push(a[i]);
while (ps[i] + offset < psm)
{
cnt++;
offset -= small_heap.top() * 2;
small_heap.pop();
}
}
cout << cnt << endl;
}
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi