Vijos 1617 超级教主

原题链接

题解

\(f[i]\) 表示跳到 \(i\) 所能取到的最大价值,则我们需要取一个 \(j(j<i)\) 使 \(f[j]+sum[i]-sum[j]-i*100\) 最大,其中 \(sum\) 数组表示前缀和,所以转移方程即为:

\[f[i]=\max(f[j]+sum[i]-sum[j]-i*100) \]

将常数提出:

\[f[i]=\max(f[j]-sum[j])+sum[i]-i*100 \]

用单调队列维护即可。

Code:

#include<bits/stdc++.h>
#define int long long
using namespace std;
void read(int &x)
{
	char ch=getchar();
	int r=0,w=1;
	while(!isdigit(ch))w=ch=='-'?-1:1,ch=getchar();
	while(isdigit(ch))r=(r<<3)+(r<<1)+(ch^48),ch=getchar();
	x=r*w;
}
const int N=2e6+100;
int a[N],f[N],line[N],s[N];
main()
{
	int n,m;
	read(n);read(m);
	for(int i=1;i<=n;i++)
		read(a[i]),s[i]=s[i-1]+a[i],f[i]=INT_MIN;
	f[0]=m;
	int head=1,tail=0;
	for(int i=0;i<=n;i++)
	{
		while(head<=tail&&f[line[tail]]-s[line[tail]]<f[i]-s[i])tail--;
		line[++tail]=i;
		while(head<=tail&&f[line[head]]<i*100)head++;
		f[i]=f[line[head]]-s[line[head]]+s[i]-i*100;
	}
	cout<<f[n];
	return 0;
}
posted @ 2022-07-06 10:57  Epoch_L  阅读(9)  评论(0编辑  收藏  举报