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")