poj 3017 单调队列优化动态规划

思路:dp[i]=min{dp[j]+max(num[j+1]...num[i])},其中sum[i]-sum[j]<=m。

那么我们需要用单调队列维护j到i的最大值。

#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<string>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define pb push_back
#define mp make_pair
#define Maxn 100010
#define Maxm 200010
#define Y 1100
#define LL __int64
#define Abs(x) ((x)>0?(x):(-x))
#define lson(x) (x<<1)
#define rson(x) (x<<1|1)
#define lowbit(x) (x&(-x))
#define clr(x,y) memset(x,y,sizeof(x))
#define Mod 1000000007
using namespace std;
LL dp[Maxn],num[Maxn];
int que[Maxn],head,rear;
LL sum[Maxn];
int main()
{
    int i,j,k,f,n;
    LL m;
    scanf("%d%I64d",&n,&m);
    clr(sum,0);
    clr(dp,0);
    f=0;
    for(i=1;i<=n;i++){
        scanf("%I64d",num+i);
        if(num[i]>m)
            f=1;
        sum[i]=sum[i-1]+num[i];
    }
    if(f){
        printf("-1
");
        return 0;
    }
    head=1,rear=0;
    j=0;
    for(i=1;i<=n;i++){
        while(sum[i]-sum[j]>m)
        j++;
        while(que[head]<=j&&head<=rear) head++;
        while(num[que[rear]]<num[i]&&head<=rear) rear--;
        que[++rear]=i;
        dp[i]=dp[j]+num[que[head]];
        for(k=head;k<rear;k++){
            dp[i]=min(dp[i],dp[que[k]]+num[que[k+1]]);
        }
    }
    printf("%I64d
",dp[n]);
    return 0;
}
原文地址:https://www.cnblogs.com/wangfang20/p/3331009.html