Since you are the best Wraith King, Nizhniy Magazin «Mir» at the centre of Vinnytsia is offering you a discount.
You are given an array a of length n and an integer c.
The value of some array b of length k is the sum of its elements except for the smallest. For example, the value of the array[3, 1, 6, 5, 2] with c = 2 is 3 + 6 + 5 = 14.
Among all possible partitions of a into contiguous subarrays output the smallest possible sum of the values of these subarrays.
The first line contains integers n and c (1 ≤ n, c ≤ 100 000).
The second line contains n integers ai (1 ≤ ai ≤ 109) — elements of a.
Output a single integer — the smallest possible sum of values of these subarrays of some partition of a.
3 5 1 2 3
6
12 10 1 1 10 10 10 10 10 10 9 10 10 10
92
7 2 2 3 6 4 5 7 1
17
8 4 1 3 4 5 5 3 4 1
23
In the first example any partition yields 6 as the sum.
In the second example one of the optimal partitions is [1, 1], [10, 10, 10, 10, 10, 10, 9, 10, 10, 10] with the values 2 and 90 respectively.
In the third example one of the optimal partitions is [2, 3], [6, 4, 5, 7], [1] with the values 3, 13 and 1 respectively.
In the fourth example one of the optimal partitions is [1], [3, 4, 5, 5, 3, 4], [1] with the values 1, 21 and 1 respectively.
题意:给你一个长为n的序列,然后给你一个常数c,让你将序列分成若干段,每一段去掉len/c个最小的数(len为这一段的长度),让你使得最终剩下的数之和最小。
题解:设dp[i]表示前i个数能删掉的元素的最大和,为了确保每次删掉的都是最小的几个元素,我们可以用set维护一下,每次将应想到的直接插入或者删除,然后直接dp即可。
#include<set>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxn 100005
#define ll long long
ll a[100005],dp[100005],n,c,ans;
multiset<ll>t;multiset<ll>:: iterator it;
int main(void)
{
scanf("%lld%lld",&n,&c);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(int i=1;i<=min(n,c-1);i++)
t.insert(a[i]);
for(int i=1;i<=n;i++)
{
dp[i+1]=max(dp[i+1],dp[i]);
if(i+c-1<=n)
{
t.insert(a[i+c-1]);
dp[i+c]=max(dp[i+c],dp[i]+(*t.begin()));
}
it=t.find(a[i]);t.erase(it);
}
ans=-dp[n+1];
for(int i=1;i<=n;i++)
ans+=a[i];
printf("%lld\n",ans);
return 0;
}