[CF 1107G] Vasya and Maximum Profit

题目

洛谷 here

题意

给出 n n n 个任务,每个任务有一个困难值 d i d_i di,困难值是递增的。而做每个任务还需要支付 c i c_i ci 元钱。解决每个任务后,可以得到 a a a 元钱。

总共挣到的钱是这么算的:

  • 首先,如果选择做第 i i i 个任务,得支付 c i c_i ci
  • 然后他可以得到 a a a
  • 那么困难度是 d i d_i di 有什么用呢?对于选择做了 [ l , r ] [l,r] [l,r] 的任务,还需支付额外的 g a p gap gap g a p ( l , r ) = max ⁡ i   =   l r − 1 ( d i + 1 − d i ) 2 gap(l,r)=\max_{i\ =\ l}^{r-1}(d_{i+1}-d_i)^2 gap(l,r)=maxi = lr1(di+1di)2。若 l = = r l==r l==r g a p ( l , r ) = 0 gap(l,r)=0 gap(l,r)=0

找出收益最大的一个区间 [ l , r ] [l,r] [l,r]

思路

那么,这似乎是求一个区间最大值?

首先, n < = 3 e 5 n<=3e5 n<=3e5 n 3 n^3 n3 的暴力肯定是不行的,让我们考虑如何优化。

记选取 [ l , r ] [l,r] [l,r] 的答案为 A n s ( l , r ) Ans(l,r) Ans(l,r), 定义 C s [ x ] Cs[x] Cs[x] [ 1 , x ] [1,x] [1,x] c c c 的总和。则:

A n s ( l , r ) = ( r − l + 1 ) ∗ a − C s [ r ] + C s [ l − 1 ] − g a p ( l , r ) Ans(l,r)=(r-l+1)*a-Cs[r]+Cs[l-1]-gap(l,r) Ans(l,r)=(rl+1)aCs[r]+Cs[l1]gap(l,r)
A n s ( l , r ) + l ∗ a − a − C s [ l − 1 ] = r ∗ a − C s [ r ] − g a p ( l , r ) Ans(l,r)+l*a-a-Cs[l-1]=r*a-Cs[r]-gap(l,r) Ans(l,r)+laaCs[l1]=raCs[r]gap(l,r)
对于固定的 l l l:左边是固定的;
那么我们能不能维护出右边的最大值呢?答案是肯定的。

如果只有 r ∗ a − C s [ r ] r*a-Cs[r] raCs[r] 这一项,似乎很简单了。然而有一个 g a p ( l , r ) , g a p ( l , r ) = max ⁡ i   =   l r − 1 ( d i + 1 − d i ) 2 gap(l,r),gap(l,r)=\max_{i\ =\ l}^{r-1}(d_{i+1}-d_i)^2 gap(l,r)gap(l,r)=maxi = lr1(di+1di)2,这个不好搞

发现当 l l l 变成 l + 1 l+1 l+1,只会对之前 max ⁡ \max max d l + 1 − d l d_{l+1}-d_l dl+1dl 来决策的 r r r 产生影响。且因为 g a p ( l , r ) gap(l,r) gap(l,r) l l l 固定,随 r r r 单调不降,所以受影响的 r r r 一定是连续的一段。所以记录下同收影响的一段 r r r,将他们归在一起,且将这段 r r r 的另一部分价值附为 max ⁡ { r ∗ a − C s [ r ] } \max \{ r*a-Cs[r]\} max{raCs[r]}。为了方便,直接记 r ∗ a − C s [ r ] = F [ r ] r*a-Cs[r]=F[r] raCs[r]=F[r]

A n s ( l , r ) = F r [ r ] − l ∗ a + a + C s [ l − 1 ] − g a p ( l , r ) Ans(l,r)=Fr[r]-l*a+a+Cs[l-1]-gap(l,r) Ans(l,r)=Fr[r]la+a+Cs[l1]gap(l,r)

由于右边是单调不降的,左边只有增加才能改变决策,因此是正确的。时间复杂度为 O ( n ) O(n) O(n)

Ps: 做完感觉好像不是特别难?也许是太久没做了。

Code:

LL Top, Cs[MAXN], Fr[MAXN], d[MAXN];
struct node
{
	LL NowFr; // 这段的 Fr 的最大值 
	LL Maxd; // 这段 r 的 d
	LL MaxFrr; // 这段 r 的 Fr - gap(l,r) 的最大值
	node(){}
	node(LL NOWFR,LL MAXD,LL MAXFRR)
	{
		NowFr = NOWFR;
		Maxd = MAXD;
		MaxFrr = MAXFRR;
	}
}S[MAXN];
int main()
{
	LL n, a;
	read( n ); read( a );
	for (Int i = 1; i <= n; ++ i)
	{
		LL c;
		read( d[i] ); read( c );
		Cs[i] = Cs[i - 1] + c;
		Fr[i] = a * i - Cs[i];
	}
	LL Ans = Max(0, a - Cs[n] + Cs[n - 1]); // Only n Ans(n, n)
	S[0].MaxFrr = - INF;
	S[++ Top] = node(Fr[n], 0, Fr[n]); // 放 n 进去 
	for (Int l = n - 1; l >= 1; -- l) // 倒着枚举 l 
	{
		LL Pf = - INF;
		while (Top && S[Top].Maxd <= d[l + 1] - d[l])
		{
			Pf = Max(Pf, S[Top].NowFr);
			S[Top --] = node(0, 0, 0);
		}
		// Pf : 这段由 l 决策 gap 的 Fr的最大值 
		if (Pf != - INF)
			S[++ Top] = node(Pf, d[l + 1] - d[l], Max(Pf - (d[l + 1] - d[l]) * (d[l + 1] - d[l]), S[Top - 1].MaxFrr));
		// 将这一段缩成一点 
		S[++ Top] = node(Fr[l], 0, Max(Fr[l], S[Top - 1].MaxFrr));
		Ans = Max(Ans, S[Top].MaxFrr - a * l + a + Cs[l - 1]);
	}
	printf("%lld", Ans); 
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值