JOI2013春合宿 day1 たのしい画像収集 (Collecting Images is Fun)
問題
日本語なので本文参照(http://imoz.jp/data/joi/2013-sp-d1-collecting.pdf)
制約条件
N≦20
Q≦2000000
方針
解説スライド(http://japl.pl/slides/joi/collecting_images_is_fun.pdf)の通り。
「白と黒が混在するマスの個数を数えればいい」ことに気づくかが全て。
あとは適当にsegment treeっぽく、上にたどって個数を更新する作業をやればいい。
ソースコード
int n, q; int cntr[20], cntc[20]; vi r[21], c[21]; //0: white 1: black 2: mixed inline void func(vi r[21], int *cntr, int b){ r[n][b] ^= 1; b /= 2; for(int i = n - 1; i >= 0; i--, b /= 2){ int prev = r[i][b]; if(r[i + 1][b * 2] == r[i + 1][b * 2 + 1]) r[i][b] = r[i + 1][b * 2]; else r[i][b] = 2; if(prev != r[i][b]){ if(prev == 2) cntr[i]--; else cntr[i]++; } } } int main(){ scanf("%d%d", &n, &q); rep(i, n + 1){ r[i].resize(1 << i); c[i].resize(1 << i); } while(q--){ int a, b; scanf("%d%d", &a, &b); b--; if(a == 0) func(r, cntr, b); else func(c, cntc, b); ll ans = 0; rep(i, n){ ans += cntr[i] * (1ll << i) + cntc[i] * (1ll << i); ans -= (ll)cntr[i] * cntc[i]; } printf("%lld\n", ans * 4 + 1); } return 0; }