D - Pyramid Editorial by evima
別解ピラミッド数列を左半分(\(1, 2, \dots, k\): これを長さ \(k\) の左ピラミッド数列と呼びます)と右半分(\(k, k-1, \dots, 1\): 長さ \(k\) の右ピラミッド数列)に分けて考えましょう。
各整数 \(i\) \((1 \leq i \leq N)\) に対し、 \(A_i\) を右端とする最長の左ピラミッド数列の長さを \(l_i\) とします。(つまり、\(A_{i-l_i+1}, A_{i-l_i+2}, \dots, A_i\) は左ピラミッド数列で、この左端に \(A_{i-l_i}\) を加えたものは左ピラミッド数列ではありません。)また、便宜上 \(l_0 = 0\) とします。このとき、\(l_i = \min(A_i, l_{i-1} + 1)\) が成立し、\(l_1, l_2, \dots, l_N\) をこの順に計算できます。
同様に、各整数 \(i\) \((1 \leq i \leq N)\) に対し、 \(A_i\) を左端とする最長の右ピラミッド数列の長さを \(r_i\) とします。(つまり、\(A_i, A_{i+1}, \dots, A_{i+r_i-1}\) は右ピラミッド数列で、この右端に \(A_{i+r_i}\) を加えたものは右ピラミッド数列ではありません。)また、便宜上 \(r_{N+1} = 0\) とします。このとき、\(r_i = \min(A_i, r_{i+1} + 1)\) が成立し、\(r_N, r_{N-1}, \dots, r_1\) をこの順に計算できます。
問題の答えは \(\min(l_1, r_1), \min(l_2, r_2), \dots, \min(l_N, r_N)\) のうち最大のものであり、線形時間で求められます。
実装例(Python)
N = int(input())
A = [0] + list(map(int, input().split()))
l, r = [0] * (N + 2), [0] * (N + 2)
for i in range(1, N + 1):
l[i] = min(A[i], l[i - 1] + 1)
for i in range(N, 0, -1):
r[i] = min(A[i], r[i + 1] + 1)
print(max(min(l[i], r[i]) for i in range(1, N + 1)))
posted:
last update: