Solution - 「Vjios 1617」超级教主

https://vijos.org/p/1617

单调队列优化 DP。

\(dp_i\) 表示跳完前 \(i\) 个能量球所需的花费。

可得:\(dp_i=\max(dp_k-100\times x+\sum^{i}_{j=k+1} h_j)\)

对此 DP 柿子进行化简:

\[dp_i=\max(dp_k-100\times x+\sum^{i}_{j=k+1} h_j)\\dp_i=\max(dp_k-100\times x+sum_i-sum_k(sum 为前缀和))\\dp_i=\max(dp_k-sum_k)-100\times x+sum_i \]

同时该 DP 柿子也要满足 \(dp_k\ge 100\times x\)

可以利用单调队列进行优化。

#include<bits/stdc++.h>
using namespace std;
const int N=2000010;
int dl[N+5],l=1,r=0;
int sum[N+5],dp[N+5];
int n,m;
int main() {
	scanf("%d %d",&n,&dp[0]);
	for(int i=1,x;i<=n;i++) {
	    scanf("%d",&x);
		sum[i]=sum[i-1]+x;	
	}
	l=1,r=1,dl[1]=0;
	for(int i=1;i<=n;i++) {
	    while(l<=r&&dp[i]-sum[i]>dp[dl[r]]-sum[dl[r]])
	        r--;
	    dl[++r]=i;
	    while(l<=r&&dp[dl[l]]<100*i)
	        l++;
	    dp[i]=dp[dl[l]]-sum[dl[l]]-100*i+sum[i];
	}
	printf("%d\n",dp[n]);
}
posted @ 2020-07-31 17:14  时一月  阅读(150)  评论(0)    收藏  举报