这是看了论文之后来做的。。。。
但是论文上有个地方没看懂,
论文上说:3 来看一个最重要的性质:如果一个决策 k 能够成为状态 f(x)的最优决策,当且仅当 ] ,1[],[][ x kjjaka 。为什么呢?其实证明非常非常容易(用到性质 1),交给读者自己思考
妈蛋啊,我证不粗来啊!我脑袋笨啊有木有!现在最怕看到的就是作者说“其实证明非常容易,交给读者自己思考”。。。。。都是泪
可惜这题,这里是关键啊,要是想不出这个性质根本没半法优化啊。。。。意思就是。。。。我特么自己做的话根本做不出来啊!伤心啊!有木有!
哎。。。。
而且还看了别人的题解,一开始想自己写的时候想着挺麻烦的。。。。看了别人的代码,真特么的优美啊,给个传送点击打开链接
还有这题用到了BST,一开始以为要自己写,不知道multiset这个数据结构可以直接用。。。
AC代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
using namespace std;
long long dp[110000], N, M, sum;
int pos[110000], num[110000], s, e, p;
multiset<long long> optset;
int main(){
while( scanf( "%lld%lld", &N, &M ) != EOF ){
for( int i = 1; i <= N; i++ ){
scanf( "%d", &num[i] );
}
s = 0; e = -1;
p = 1; sum = 0;
optset.clear();
int flag = 0;
for( int i = 1; i <= N; i++ ){
if( num[i] > M ){
flag = 1;
break;
}
sum += num[i];
while( sum > M )
sum -= num[p++];
while( s <= e && num[i] > num[pos[e]] ){
if( s < e )
optset.erase( dp[pos[e-1]] + num[pos[e]] );
--e;
}
pos[++e] = i;
if( s < e )
optset.insert( dp[pos[e-1]] + num[i] );
while( pos[s] < p ){
if( s < e )
optset.erase( dp[pos[s]] + num[pos[s+1]] );
s++;
}
dp[i] = dp[p-1] + num[pos[s]];
if( s < e && dp[i] > *optset.begin() ){
dp[i] = *optset.begin();
}
}
if( flag ){
dp[N] = -1;
}
printf( "%lld\n", dp[N] );//这里不能用cout
}
return 0;
}