https://loj.ac/problem/10177

今天的考试题目中有单调队列优化dp的,感觉不太熟练,所以练几手题

其实这题就是今天的T2!!!!

首先是dp很明确

dp[i,0]表示处理了前i个位置,并且第i个位置不选的最大值

dp[i,1]表示处理了前i个位置,并且第i个位置要选的最大值

明显dp[i,0]=max(dp[i-1,0],dp[i-1,1]);

dp[i,1]=dp[j,0]+sum[i]-sum[j],(i-k<=j<i)

又是维护移动区间,维护递减的单调队列

code by wzxbeliever:

#include<bits/stdc++.h>
#define ll long long
#define il inline
#define ri register int
#define lowbit(x) x&(-x)
using namespace std;
const int maxn=1e5+5;
int n,k,head=1,tail=1;
il ll maxl(ll a,ll b){if(a>b)return a;return b;}
ll num[maxn],a[maxn],sum[maxn],dp[maxn][2];
int main(){
    scanf("%d%d",&n,&k);
    for(ri i=1;i<=n;i++)scanf("%lld",&a[i]),sum[i]=sum[i-1]+a[i];
    for(ri i=1;i<=n;i++){
    dp[i][0]=maxl(dp[i-1][0],dp[i-1][1]);
    while(head<=tail&&num[head]<i-k)head++;
    dp[i][1]=dp[num[head]][0]-sum[num[head]]+sum[i];
    while(head<=tail&&dp[i][0]-sum[i]>dp[num[tail]][0]-sum[num[tail]])tail--;
    num[++tail]=i;
    }
    printf("%lld\n",maxl(dp[n][0],dp[n][1]));
    return 0;
}
02-12 02:09