Time limit 2000 ms
Memory limit 262144 kB
Source Educational Codeforces Round 69 (Rated for Div. 2)
Tags dp greedy math *1900
Editorial Announcement (en) Tutorial #1 (en) Tutorial #2 (en) Tutorial #3 (ru)
官方题解
At first let's solve this problem when m=1m=1 and k=0k=0 (it is the problem of finding subarray with maximum sum). For each position from 11 to nn we want to know the value of maxli=max1≤j≤i+1sum(j,i)maxli=max1≤j≤i+1sum(j,i), where sum(l,r)=∑k=lk≤raksum(l,r)=∑k=lk≤rak, and sum(x+1,x)=0sum(x+1,x)=0.
We will calculate it the following way. maxlimaxli will be the maximum of two values:
- 00 (because we can take segments of length 00);
- ai+maxli−1ai+maxli−1.
The maximum sum of some subarray is equal to max1≤i≤nmaxlimax1≤i≤nmaxli.
So, now we can calculate the values of besti=max0≤len,i−len⋅m≥0(sum(i−len⋅m+1,i)−len∗k)besti=max0≤len,i−len⋅m≥0(sum(i−len⋅m+1,i)−len∗k) the same way.
bestibesti is the maximum of two values:
- 0;
- sum(i−m+1,i)−k+besti−msum(i−m+1,i)−k+besti−m.
After calculating all values bestibesti we can easily solve this problem. At first, let's iterate over the elements bestibesti. When we fix some element bestibesti, lets iterate over the value len=1,2,…,mlen=1,2,…,m and update the answer with value besti+sum(i−len,i−1)−kbesti+sum(i−len,i−1)−k.
源代码
#include<stdio.h>
#include<algorithm>
int n,m,k;
long long a[300010];
long long dp[300010],ans;
int main()
{
//freopen("test.in","r",stdin);
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++) scanf("%lld",a+i),a[i]+=a[i-1];
for(int i=1;i<=n;i++)
{
for(int j=i;j+m>=i;j--)
dp[i]=std::max(dp[i],a[i]-a[j]);
dp[i]-=k;
dp[i]=std::max(0LL,dp[i]);
if(i>m) dp[i]=std::max(dp[i],dp[i-m]+a[i]-a[i-m]-k);
ans=std::max(dp[i],ans);
}
printf("%lld\n",ans);
return 0;
}