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;
}