1st Try: brutal-force solution failed 3 test cases with TLE
2nd Try: uint32_t bucketing - AC:
#include <cstdio> #include <string> #include <algorithm> #include <vector> #include <iostream> #include <cstring> #include <cstdlib> using namespace std; #define LEN 100032 typedef unsigned long long ULL; unsigned ia[LEN/32] = {0}; unsigned ib[LEN/32] = {0}; void set_b(unsigned v[LEN/32], int b, int cnt) { if (b) // set 1 { v[cnt/32] |= 1 << (cnt % 32); } else { unsigned mask = 0; mask |= 1 << (cnt % 32); mask = ~mask; v[cnt/32] &= mask; } } int get_b(unsigned v[LEN/32], int inx) { int binx = inx % 32; int sinx = inx / 32; unsigned b = v[sinx] & (1 << (binx)); return b ? 1 : 0; } void set_v(string &s, unsigned v[LEN/32]) { size_t n = s.length(); for(int i = n - 1; i >= 0; i--) { int cnt = n - 1 - i; int b = s[i] - '0'; set_b(v, b, cnt); } } int main() { int n, q; cin >> n >> q; string a, b; cin >> a; set_v(a, ia); cin >> b; set_v(b, ib); while(q--) { string cmd; int v0 = 0, v1 = 0; cin >> cmd; if(cmd[0] == 's') { cin >> v0 >> v1; if(cmd[4] == 'a') { set_b(ia, v1, v0); } if(cmd[4] == 'b') { set_b(ib, v1, v0); } } if(cmd[0] == 'g') { cin >> v0; int sinx = v0 / 32; int binx = v0 % 32; unsigned sum = ia[sinx] + ib[sinx]; unsigned bv = sum & (1 << binx); if(binx > 0) { unsigned tail = (1 << binx) - 1; if ((sum & tail) < tail) // no need to check prev. { cout << (bv ? 1 : 0); continue; } } bool bCarry = false; sinx --; while(sinx >= 0) { ULL sum = (ULL)ia[sinx] + (ULL)ib[sinx]; if (sum < 0xFFFFFFFF) { bCarry = false; break; } else if(sum > 0xFFFFFFFF) { bCarry = true; break; } sinx --; } // if (!bCarry) cout << (bv ? 1 : 0); else cout << (bv ? 0 : 1); } } return 0; }
By checking the LeaderBoard, I learnt a beautiful SegTree solution:
class Node { public: int bit; // 0\1: bits[left, right] are all 0\1; // -1: bits[left, right] are not same int left, right; // range: bits[left, right] };
Each node takes in charge of a range of bits, and records bits values of the range. And we update\query bits of sum upon this SegTree.. Neat!