朴素的话f[i]=f[j]+maxdata[j+1,i],是n^2的,必须优化。我们发现对于递增的i,其决策与是不减的,我们想到了单调队列。
我们发现,有效的决策是一个递减的序列,这是因为f[i]是单调的。而且如果维护这样的队列,就不需要事先预处理做RMQ了。
那么这道题有什么玄机呢?有的,这道题目维护单调队列时的条件不能直接导致队首的值最优,这意味着如果我们扫一遍取最优值的话还是n^2。
所以我们就要借助数据结构优化了,带索引的堆或者平衡树都可以,关键是要随着单调队列元素的增删而增删。复杂度降为nlogn。
决策下界处需要单独特判,而且插入和删除BST元素的时候也要仔细再仔细。
//By YY_More
#include<cstdio>
#include<set>
using namespace std;
int D[100010],a[100010],L,R,N,low;
long long M,sum,f[100010],temp;
multiset<int> tree;
int main(){
scanf("%d%I64d",&N,&M);
for (int i=1;i<=N;i++)
scanf("%d",&a[i]);
L=0;R=-1;sum=0;low=1;
bool flag=true;
for (int i=1;i<=N;i++){
sum+=a[i];
while (sum>M) sum-=a[low++];
if (low> i){
L=0;R=-1;printf("-1");flag=false;break;
}
while (L<=R&&a[i]>=a[D[R]]) {
if (R>L) tree.erase(f[D[R-1]]+a[D[R]]);
R--;
}
D[++R]=i;if (R>L) tree.insert(f[D[R-1]]+a[D[R]]);
while (low>D[L]) {
if (R>L) tree.erase(f[D[L]]+a[D[L+1]]);
L++;
}
temp=*(tree.begin());f[i]=f[low-1]+a[D[L]];
if (L<R&&temp<f[i]) f[i]=temp;
}
if (flag) printf("%I64d",f[N]);
return 0;
}