codeforces 1197D-Yet Another Subarray Problem

Portal: QAQQAQ

 

Question is intended: to give you a sequence, subsequence a seeking a [l] ~ a [r] such that the sum of the subsequence (l, r) -k * (r-l + 1 + m + 1) / m value of in the largest of all the sub-sequence, and outputs the maximum value

 

Ideas: the game when using O (n) to write, but was hack, because O (n) -k can not record how much time, if monotonous queue maintains do not know how much should pop up in front of (now possible under the current distance the front pop-up is the best, but probably because of the number to the back not to the multiple of m, is added to the list in front of the best), so we consider plus a one-dimensional

 

Method a: dp [i] [j] to i off a sequence, which has an access time of j (j = (len + m-1)% m), then the DP [i] [j] maintained is the starting point of s = i-j + 1-m * set the optimal t (t> = 0), so that all the dp [i] [j] can maintain an optimal answer in the off i

Updating the current i there are two cases: the first is that currently only take a [i] in the dp [i] [1] Unexamined determination to

            The second is also taken foregoing, dp [i] [j] from dp [i-1] [j-1] (as dp [i-1] s set [j-1] and maintained DP [ i] [j] s is maintained by a set of the same) to transfer (note the boundary conditions)

(HCY before metaphysics another layer cycle update, has not read, although he later discovered that the answer is right, but only 1 m update times are valid)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const ll inf=200000000000000;
 
int n,m;
ll ans=0,dp[300005][20],sum[300005],a[300005],k;
 
int main()
{
    scanf("%d%d%lld",&n,&m,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=m;j++) dp[i][j]=-inf;
    }
    dp[1][1]=a[1]-k; 
    for(int i=2;i<=n;i++)
    {
        dp[i][1]=a[i]-k;
        for(int j=1;j<=min(i,m);j++)
        {
            if(j==1) dp[i][j]=max(dp[i][j],dp[i-1][m]+a[i]-k);
            else dp[i][j]=max(dp[i][j],dp[i-1][j-1]+a[i]); 
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++) ans=max(ans,dp[i][j]);
    }
    cout<<ans<<endl;
    return 0;
}//

 

Act II:

And the game I like the idea, but here an added layer of maintenance start_point% m = rnd, m times can be emulated foot (in enough time, the confused current monotonous queue several pop-up is the best and then enumerate, so do not worry about what the front to pop up, simply len% m = 0 when determining whether or not to reset to the starting point)

That is, if the current minus k * t is less than 0, then re-start, or continue to add

Note ans will be updated each time a backward extension

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=300005;
ll ans=0,n,a[N],m,k;
 
int main()
{
    scanf("%lld%lld%lld",&n,&m,&k);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    for(int rnd=1;rnd<=m;rnd++)
    {
        ll len=0; ll now=0;
        for(int i=rnd;i<=n;i++)
        {
            if(len%m==0) if(now-len/m*k<0) now=0,len=0;
            now+=a[i]; len++;
            ans=max(ans,now-(len+m-1)/m*k);
        }
    }
    cout<<ans<<endl;
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/Forever-666/p/11241525.html