W - 隣接加算/Adjacent Add 解説 by harurun4635


数列を「左が上の桁の \(-2\) 進数」として解釈した値を考えます。

「 \(A[l:r]\) に対する値」と「 \((C, \dots, C)\) に対する値」が一致すれば、すべて \(C\) にできます。


この \(C\) の値がわかれば、適当な \(\bmod\) 上で計算すれば確率的な一致判定ができます。

この \(C\) は、上のほうの桁 \(A[l:l+60]\) 程を愚直に見れば、下の桁では大きく変化させることができないため、(決定的に)求めることができます。(くわしくは実装例を参照してください)


実装例

from atcoder.segtree import SegTree

mod = (1 << 61) - 1

def op(a, b):
    return ((a[0] * b[1] + b[0]) % mod, a[1] * b[1] % mod)

n, q = map(int, input().split())
a = list(map(int, input().split()))
seg = SegTree(op, (0, 1), [(x, mod - 2) for x in a])

for _ in range(q):
    t, *qry = map(int, input().split())
    if t == 1:
        i, x = qry
        a[i-1] = x
        seg.set(i-1, (x, mod - 2))
    else:
        l, r = qry
        l -= 1
        m = r - l
        k = min(m, 60)
        v = 0
        for x in a[l:l + k]:
            v = x - 2 * v
        d = (1 - (-2) ** k) // 3

        if m <= 60:
            print("Yes" if v % d == 0 else "No")
        else:
            c = (2 * v + d) // (2 * d)
            h, p = seg.prod(l, r)
            print("Yes" if (3 * h - c * (1 - p)) % mod == 0 else "No")