习题:Vasya and Maximum Profit(单调栈&DP)

题目

传送门

思路

对于一个区间\(l到r\),答案即为

\(\begin{aligned}val_{l,r}=&a*(r-l+1)-max_{i=l}^{r-1}(d_{i+1}-d_i)^2-\sum_{i=l}^rc_i\\=&a*r-a*(l-1)-max_{i=l}^{r-1}(d_{i+1}-d_i)^2-sum_r+sum_{l-1}\end{aligned}\)

\(val_{l,r}+a*(l-1)-sum_{l-1}=a*r-max_{i=l}^{r-1}(d_{i+1}-d_i)^2-sum_r\)

左边的很明显是固定的,只需要右边最大即可

考虑从n到1来扫,只需要用单调栈来优化即可

代码

#include<iostream>
using namespace std;
struct node
{
	long long f;
	long long maxx;
	long long maxr;
};
int n,top;
long long a;
long long ans;
long long d[300005],f[300005],sum[300005];
node s[300005];
int main()
{
	cin>>n>>a;
	for(int i=1;i<=n;i++)
	{
		long long x;
		cin>>d[i]>>x;
		sum[i]=sum[i-1]+x;
		f[i]=a*i-sum[i];
	}
	ans=max(a+sum[n-1]-sum[n],0ll);
	s[++top]=(node){f[n],0,f[n]};
	s[0].maxr=-(1ll<<60);
	for(int i=n-1;i>=1;i--)
	{	
		long long maxf=-(1ll<<60);
		while(top&&d[i+1]-d[i]>=s[top].maxx)
		{
			maxf=max(maxf,s[top].f);
			top--;
		}
		if(maxf!=-(1ll<<60))
		{
			top++;
			s[top]=(node){maxf,d[i+1]-d[i],max(maxf-(d[i+1]-d[i])*(d[i+1]-d[i]),s[top-1].maxr)};
		}
		s[++top]=(node){f[i],0,max(f[i],s[top-1].maxr)};
		ans=max(ans,s[top].maxr-a*i+a+sum[i-1]);
	}
	cout<<ans;
	return 0;
}
posted @ 2020-08-24 16:30  loney_s  阅读(130)  评论(0)    收藏  举报