コンテンツにスキップ

Blitz Round #25 B - Jump Trip Score

サイト
EOLYMP
コンテスト
Blitz Round #25
問題
B - Jump Trip Score

長さ nn の整数列 a1,…,ana_1, \ldots, a_n があり、位置 i=1i = 1 から出発して i=n+1i = n + 1 に着いたら終わりです。スコアは 00 から始まり、各位置で次のどちらかを行います。

  • aia_i をスコアに足して i+1i + 1 に進む
  • 正の整数 dd (i+d≤n+1i + d \le n + 1) を選んで i+di + d に跳ぶ(スコアは変わらない)

跳ぶ操作は高々 1 回まで使えるとき、最終スコアの最大値を求める問題です。

  • 1≤n≤4⋅1051 \le n \le 4 \cdot 10^5、−109≤ai≤109-10^9 \le a_i \le 10^9、テストケースの nn の総和は 4⋅1054 \cdot 10^5 以下

正確な問題文は元の問題ページを見てください。

ii から i+di + d に跳ぶと、ai,…,ai+d−1a_i, \ldots, a_{i+d-1} を飛ばすことになります。跳ぶのは高々 1 回なので、得られるスコアは

(先頭からの連続部分の和)+(末尾までの連続部分の和)(\text{先頭からの連続部分の和}) + (\text{末尾までの連続部分の和})

で、間の 1 区間を飛ばした形になります(跳ばなければ全部の和)。

そこで

  • LkL_k = 長さ kk 以下の接頭辞の和の最大値(空も含むので 00 以上)
  • RkR_k = 位置 k+1k + 1 以降から始まる接尾辞の和の最大値(空も含む)

を累積和で求めておけば、答えは

max⁡0≤k≤n(Lk+Rk)\max_{0 \le k \le n} (L_k + R_k)

です。接頭辞と接尾辞が重ならないように、境目 kk を全通り試しています。計算量は O(n)O(n) です。

Python
for _ in range(int(input())):
N = int(input())
A = list(map(int,input().split()))
dp0 = [0]
x = 0
for a in A:
x += a
dp0.append(max(x, dp0[-1]))
dp1 = [0]
x = 0
for a in reversed(A):
x += a
dp1.append(max(x, dp1[-1]))
dp1.reverse()
print(max(x+y for x,y in zip(dp0,dp1)))

dp0 が LL、dp1 が RR にあたります。