Official

D - 特訓 Editorial by sounansya


\(A_i\) を全て \(A_i - K\) に置き換えることで、 \(K=0\) の場合に帰着させることができます。以降は \(K=0\) の場合を考えます。

特訓期間を \(L\) 日目から \(R\) 日目までとすると、条件は数式で表すと \(\displaystyle \frac1{R-L+1}\sum_{i=L}^R A_i \le 0\) となります。

\(R-L+1 > 0\) より、条件は \(\displaystyle \sum_{i=L}^R A_i \le 0\) と同値であることも分かります。

ここで、 \(A\) の累積和を \(B\) 、つまり \(\displaystyle B_i=\sum_{j=1}^i A_j\) とすると、条件は \(B_R - B_{L-1} \le 0\) となります。つまり、問題は \(B_R \le B_{L-1}\) を満たす整数の組 \((L,R)\) \((L \le R)\) 全てにおける \(R-L+1\) の最大値となります。これは LIS を求める場合と同じように、 \(L\) の候補を単調減少列として持ちながら \(R\) に対して二分探索していくことで求めることができます。

以上を適切に実装することでこの問題に正答することができます。計算量は \(O(N \log N)\) です。

実装例(Python3)

n, k = map(int, input().split())
a = [0] + list(map(int, input().split()))
for i in range(n):
    a[i + 1] += a[i] - k
for i in range(n + 1):
    a[i] *= -1
q = [(10**18, -1)]
ans = 0
for i in range(n + 1):
    if q[-1][0] > a[i]:
        q.append((a[i], i))
    ng, ok = 0, len(q)
    while ok - ng != 1:
        vs = (ok + ng) >> 1
        if q[vs][0] <= a[i]:
            ok = vs
        else:
            ng = vs
    ans = max(ans, i - q[ok][1])
print(ans)

posted:
last update: