单调队列优化dp——bzoj2442

/*
dp[i][0|1]表示选|不选第i只奶牛可获得的最大收益
dp[i][0]=max(dp[i-1][0],dp[i-1][1])
dp[i][1]=max(dp[x][0]+sum[i]-sum[x])
转化得到 dp[i][1]=max(dp[x][0]-sum[x])+sum[i]
    那么dp[x][0]-sum[x]就可以用单调队列来维护                  
*/ 
#include<bits/stdc++.h>
#include<queue>
using namespace std;
#define ll long long 
#define N 200005

ll n,a[N],sum[N],m,dp[N][2];

int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];
    deque<int>q;
    q.push_back(0);
    for(int i=1;i<=n;i++){
        dp[i][0]=max(dp[i-1][0],dp[i-1][1]);
        if(q.size()==0){
            dp[i][1]=a[i];
            q.push_back(i);
        }else {
            while(q.size()){
                int p=q.front();
                if(i-p>m){q.pop_front();continue;}
                else {
                    dp[i][1]=sum[i]+dp[p][0]-sum[p];
                    break;
                }
            }
            while(q.size()){
                int p=q.back();
                if(dp[p][0]-sum[p]<=dp[i][0]-sum[i])
                    q.pop_back();
                else break;
            }
            q.push_back(i);
        }
    }
    cout<<max(dp[n][0],dp[n][1])<<'\n';
} 

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/12510294.html
今日推荐