YY_More

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

朴素的话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;
}
posted on 2011-06-27 23:19  YY_More  阅读(2346)  评论(0编辑  收藏  举报