/*
dp[i]表示前i个数的最优解
dp[i]=min{ dp[j]+max[j+1,i] },sum[i]-sum[j]<=M
使用决策单调性:显然dp[i]是单调递增的
那么维护一个区间[j+1,i]关于a的递减单调队列q
对于a[q[1]]可以控制的决策范围是[j+1,q[1]],又因为决策单调性,所以这一段区间的最优解就是dp[j+1]+a[q[1]]
同理,遍历整个队列,可得后面每一段的最佳决策
*/
#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
#define ll long long
#define N 200005
ll n,M,a[N],sum[N],dp[N];
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];
for(int i=1;i<=n;i++)if(a[i]>M){
puts("-1");return 0;
}
memset(dp,0x3f,sizeof dp);dp[0]=0;
deque<int>q;
deque<int>::iterator it,itt;
int pos=1;
for(int i=1;i<=n;i++){
while(sum[i]-sum[pos-1]>M)pos++;
while(q.size()){//删前面
int p=q.front();
if(sum[i]-sum[p-1]>M)q.pop_front();
else break;
}
while(q.size()){//删后面
int p=q.back();
if(a[p]<=a[i])q.pop_back();
else break;
}
q.push_back(i);
for(it=q.begin();it!=q.end();it++){
if(it==q.begin()){
dp[i]=min(dp[i],a[*it]+dp[pos-1]);
}else {
itt=it;itt--;
dp[i]=min(dp[i],a[*it]+dp[*itt]);
}
}
}
cout<<dp[n]<<'\n';
}
来源:https://www.cnblogs.com/zsben991126/p/12512137.html