朴素的话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; }