https://codeforces.com/problemset/problem/1175/D
题意:给出数组a和一个正整数k,将a划分成k个连续的非空子数组,每个子数组从左到右编号1到k,然后花费是每个数乘以其子数组编号的和,求最大花费。
思路:很有意思的贪心 + 前缀和。
假设第i次的分割位置为p[i],前缀和数组是sum[i]
cost = 1 * s[p1] + 2 *(s[p2] - s[p1]) + 3 * (s[p3] - s[p2])
+…+ k * s[pk];
展开得:
cost = k * s[pk] - (s[p1] + s[p2] +… + s[pk-1]);
为了使cost尽可能大,我们需要使前缀和的前k - 1项尽可能小;
所以我们将前缀和排序取前k - 1项就可以。
这里要注意的是,s[pk]其实就是s[n],s[n]是必选的,所以排序的时候不能将s[n]算进去。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + 10;
int a[maxn];
ll sum[maxn];
int main()
{
int n, k;
cin >> n >> k;
for(int i = 1;i <= n; i++)
{
cin >> a[i];
sum[i] = sum[i - 1] + a[i];
}
sort(sum + 1, sum + n);
ll ans = k * sum[n];
for(int i = 1;i < k; i++)
ans -= sum[i];
cout << ans << endl;
return 0;
}