Kick Start 2019 Round D

X or What?

The following symbol $ \ xor $ express XOR.

Notes, popcount ($ a \ xor b $) = popcount ($ a $) + popcount ($ b $) - 2 * number of positions both $ a $ and $ b $ are set.
Thus, popcount ($ a \ xor b $) parity = (popcount ($ a $) + popcount ($ b $)) parity.

Interval $ [L, R] $ popcount the exclusive OR of an even number and $ \ iff $ $ L - 1, R $ both prefixes and the exclusive OR of the parity popcount same.

XOR considered separately and the odd popcount prefix, and the XOR popcount prefix even.

Changes affect $ A_p $ of the answer:
if $ A_p $ popcount of parity unchanged, the answer is also the same, or $ p, p + 1, \ dots, n - 1 $ these prefixes XOR and the popcount parity flip.

Solution 1

Maintenance and XOR parity prefix popcount with tree line.
XOR and support queries of popcount is (odd / even) prefix (first / last) position appears.

bool bit_even(int x) {
    return (__builtin_popcount(x) & 1) == 0;
}

struct node {
  int n[2];
  int flipped;
  void flip() {
      swap(n[0], n[1]);
      flipped ^= 1;
  }
};
const int N = 100005;
node seg[4 * N];

int sum[N];
void push_up(int i) {
    int l = i * 2, r = l + 1;
    for (int j = 0; j < 2; j++) {
        seg[i].n[j] = seg[l].n[j] + seg[r].n[j];
    }
}

void build (int i, int l, int r) {
    seg[i].flipped = 0;
    if (l == r) {
        seg[i].n[0] = bit_even(sum[l]);
        seg[i].n[1] = 1 - seg[i].n[0];
        return;
    }
    int mid = (l + r) / 2;
    build(i * 2, l, mid);
    build(i * 2 + 1, mid + 1, r);
    push_up(i);
}

void push_down(int i) {
    if (seg[i].flipped) {
        int l = i * 2, r = i * 2 + 1;
        seg[l].flip();
        seg[r].flip();
        seg[i].flipped = 0;
    }
}

int find_first(int v, int i, int l, int r) {
    if (seg[i].n[v] == 0) return r + 1;
    if (l == r) return l;
    push_down(i);
    int mid = (l + r) / 2;
    int res = find_first(v, i * 2, l, mid);
    if (res <= mid) {
        return res;
    }
    return find_first(v, i * 2 + 1, mid + 1, r);
}

int find_last(int v, int i, int l, int r) {
    if (seg[i].n[v] == 0) return l - 1;
    if (l == r) return l;
    push_down(i);
    int mid = (l + r) / 2;
    int res = find_last(v, i * 2 + 1, mid + 1, r);
    if (res > mid) {
        return res;
    }
    return find_last(v, i * 2, l, mid);
}

void flip(int i, int l, int r, int ql, int qr) {
    if (ql > r || qr < l) return;
    if (ql <= l && r <= qr) {
        seg[i].flip();
        return;
    }
    int mid = (l + r) / 2;
    push_down(i);
    flip(i * 2, l, mid, ql, qr);
    flip(i * 2 + 1, mid + 1, r, ql, qr);
    push_up(i);
}


int main() {
#ifdef LOCAL
    ifstream in("main.in");
    cin.rdbuf(in.rdbuf());
#endif
    int T; cin >> T;
    for (int cas = 1; cas <= T; ++cas) {
        cout << "Case #" << cas << ":";
        int n, q; cin >> n >> q;
        vector<int> a(n + 1);
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
            sum[i] = sum[i - 1] ^ a[i];
        }
        build(1, 1, n);
        while (q--) {
            int p, v;
            cin >> p >> v;
            ++p;
            if (bit_even(v) != bit_even(a[p])) {
                flip(1, 1, n, p, n);
            }
            a[p] = v;
            cout << " " << max(find_last(0, 1, 1, n), find_last(1, 1, 1, n) - find_first(1, 1, 1, n));
        }
        cout << endl;
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/Patt/p/11260053.html