小红的数组切割
[牛客链接](https://www.nowcoder.com/practice/ddd09898956044a5bfa0995adf30ce29)
思路
贪心 + 前缀和
每个元素 的权值为
,其中
若
,
若
,
为该元素所在块的编号。
将总权值拆成两部分:
$$
第一部分和切割无关,是个常数。关键在第二部分。
切割对块编号的影响:假设不切割,所有元素在第 1 块,此时第二部分的贡献为 。每在位置
(第
和
个元素之间)添加一刀,位置
及之后所有元素的块编号都加 1,总权值增量为:
$$
即从位置 到末尾的
后缀和。
我们最多切 刀(得到
块),因此只需从
个候选切割位置的增量中,贪心选取最大的
个正值累加即可。
以样例验证:,
,
。
- 固定项
- 不切割基础值
- 三个切割位置的增量:
,
,
- 选
个最大正值:
- 答案
,正确
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k;
scanf("%d%d", &n, &k);
vector<long long> a(n);
for (int i = 0; i < n; i++) scanf("%lld", &a[i]);
char s[100001];
scanf("%s", s);
vector<int> op(n);
for (int i = 0; i < n; i++) {
op[i] = (s[i] == '1') ? 1 : -1;
}
// 基础值:所有元素在第 1 块
long long base = 0;
for (int i = 0; i < n; i++) {
base += (long long)op[i] * a[i] + op[i];
}
// 计算每个切割位置的增量(op 的后缀和)
vector<long long> gains;
long long suffix = 0;
for (int i = n - 1; i >= 1; i--) {
suffix += op[i];
gains.push_back(suffix);
}
sort(gains.rbegin(), gains.rend());
long long ans = base;
for (int i = 0; i < k - 1 && i < (int)gains.size(); i++) {
if (gains[i] > 0) {
ans += gains[i];
} else {
break;
}
}
printf("%lld\n", ans);
return 0;
}
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int k = Integer.parseInt(st.nextToken());
long[] a = new long[n];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) {
a[i] = Long.parseLong(st.nextToken());
}
String s = br.readLine().trim();
int[] op = new int[n];
for (int i = 0; i < n; i++) {
op[i] = (s.charAt(i) == '1') ? 1 : -1;
}
// 基础值:所有元素在第 1 块
long base = 0;
for (int i = 0; i < n; i++) {
base += (long) op[i] * a[i] + op[i];
}
// 计算每个切割位置的增量
long[] gains = new long[n - 1];
long suffix = 0;
for (int i = n - 1; i >= 1; i--) {
suffix += op[i];
gains[i - 1] = suffix;
}
Arrays.sort(gains);
long ans = base;
int cnt = 0;
for (int i = gains.length - 1; i >= 0 && cnt < k - 1; i--, cnt++) {
if (gains[i] > 0) {
ans += gains[i];
} else {
break;
}
}
System.out.println(ans);
}
}
复杂度分析
- 时间复杂度:
,瓶颈在排序增量数组。
- 空间复杂度:
,存储数组和增量。

京公网安备 11010502036488号