题目描述:
Baltic, a famous chess player who is also a mathematician, has an array \(a_1,a_2,…,a_n\), and he can perform the following operation several (possibly \(0\)) times:
-
Choose some index \(i (1≤i≤n)\);
-
multiply \(a_i\) with \(−1\), that is, set \(a_i:=−a_i\).
Baltic's favorite number is \(m\), and he wants \(a_1+a_2+⋯+a_m\) to be the smallest of all non-empty prefix sums. More formally, for each \(k=1,2,…,n\) it should hold that
\[a_1+a_2+⋯+a_k≥a_1+a_2+⋯+a_m. \]Please note that multiple smallest prefix sums may exist and that it is only required that \(a_1+a_2+⋯+a_m\) is one of them.
Help Baltic find the minimum number of operations required to make \(a_1+a_2+⋯+a_m\) the least of all prefix sums. It can be shown that a valid sequence of operations always exists.
输入描述:
Each test contains multiple test cases. The first line contains the number of test cases \(t (1≤t≤10000).\) The description of the test cases follows.
The first line of each test case contains two integers \(n\) and \(m (1≤m≤n≤2⋅10^5)\) — the size of Baltic's array and his favorite number.
The second line contains \(n\) integers \(a_1,a_2,…,a_n (−10^9≤ai≤10^9)\) — the array.
It is guaranteed that the sum of \(n\) over all test cases does not exceed \(2⋅10^5\).
输出描述:
For each test case, print a single integer — the minimum number of required operations.
样例:
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
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
int T = 1;
int n, m;
LL a[N];
// 要让 m 的前缀和最小,需要让m + 1 ~ n的值都大于0,让m ~ 2的值都小于0
// 要让改变次数最少,则需要找到m + 1 ~ n中小于0的最小值,m ~ 2的大于0的最大值
void solve()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++)
scanf("%lld",&a[i]);
priority_queue<LL, vector<LL>, greater<LL>> q; // 小根堆
priority_queue<LL, vector<LL>, less<LL>> p; // 大根堆
LL sum = 0;
int ans = 0; // 要用到的次数
// 遍历m + 1 到 n
for(int i = m + 1; i <= n; i ++)
{
// m + 1 到 n 的前缀和
sum += a[i];
// 如果小于零则存进堆中
if(a[i] < 0)
q.push(a[i]);
// 和小于零则必须要将其变为正的不然m + 1 ~ n的和加上前面的数的和必然小于m的前缀和
while(sum < 0)
{
int t = q.top();
q.pop();
sum -= 2 * t;
ans ++;
}
}
sum = 0;
// 从后往前遍历,要用最少的次数
for(int i = m; i >= 2; i --)
{
sum += a[i];
// 如果大于零则存入堆中
if(a[i] > 0)
p.push(a[i]);
// 和大于零则必须将其变为负的不然m加上前面的和必然大于前面的某个数的前缀和
while(sum > 0)
{
int t = p.top();
p.pop();
sum -= 2 * t;
ans ++;
}
}
printf("%d\n", ans);
}
int main()
{
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
scanf("%d", &T);
while(T --)
solve();
return 0;
}
标签:10,int,Sum,number,Least,Prefix,test,Baltic,sum
From: https://www.cnblogs.com/KSzsh/p/17025711.html