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; }