题目
题意
给出 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 = lr−1(di+1−di)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)=(r−l+1)∗a−Cs[r]+Cs[l−1]−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)+l∗a−a−Cs[l−1]=r∗a−Cs[r]−gap(l,r)
对于固定的
l
l
l:左边是固定的;
那么我们能不能维护出右边的最大值呢?答案是肯定的。
如果只有 r ∗ a − C s [ r ] r*a-Cs[r] r∗a−Cs[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 = lr−1(di+1−di)2,这个不好搞
发现当 l l l 变成 l + 1 l+1 l+1,只会对之前 max \max max 由 d l + 1 − d l d_{l+1}-d_l dl+1−dl 来决策的 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{r∗a−Cs[r]}。为了方便,直接记 r ∗ a − C s [ r ] = F [ r ] r*a-Cs[r]=F[r] r∗a−Cs[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]−l∗a+a+Cs[l−1]−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;
}