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\n");

        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\n",dp[n]);

    return 0;

}

 

你可能感兴趣的:(动态规划)