Codeforces 339D Xenia and Bit Operations
問題
長さが2^nの配列が与えられる。
配列に対する値vを以下のように計算する。
(a[0] or a[1]), (a[2] or a[3]), (a[4] or a[5]) ...を新たな数列aとする
(a[0] xor a[1]), (a[2] xor a[3]), (a[4] xor a[5]) ...を新たな数列aとする
というように、隣接する項をペアにして、or xor or xor...としていく操作を、項が1個になるまで繰り返す。
vをそのときのa[0]とする。
(ただしor, xorはビット毎のor, xorである)
クエリがm個来る。
クエリはaのp番目の項をqにする操作である。
各クエリが終わった時点でのvの値をそれぞれ出力せよ。
制約条件
n≦17
m≦100000
a[i]<2^30
方針
適当にsegtreeを更新するだけ。
一回の操作はO(log(2^n))で、m回クエリが来るので、計算量はO(nm)
自分は誤読のときの名残でbitを30回にわけて操作をしているが、別にまとめてやればいい。
ソースコード
int n, m, a[1 << 17], b[1 << 18]; int p[100000], q[100000], ans[100000]; int main(){ scanf("%d%d", &n, &m); rep(i, 1 << n) scanf("%d", a + i); rep(i, m) scanf("%d%d", p+i, q+i), p[i]--; rep(bit, 30){ int N = (1 << n) - 1; rep(i, 1 << n) b[i + N] = a[i] >> bit & 1; rep(i, n){ N -= 1 << n-1-i; for(int j = N; j < N + (1<<n-1-i); j++) b[j] = i % 2 ? b[j*2+1] ^ b[j*2+2] : b[j*2+1] | b[j*2+2]; } assert(N == 0); rep(i, m){ int pos = p[i] + (1 << n) - 1, v = q[i] >> bit & 1; b[pos] = v; rep(j, n){ int pp = (pos-1) / 2; int x = b[pp*2+1], y = b[pp*2+2]; b[pp] = j % 2 ? x ^ y : x | y; pos = pp; } ans[i] |= b[0] << bit; } } rep(i, m) printf("%d\n", ans[i]); return 0; }