I spent most of the time stuck on Problem D and had only half an hour left when I wrote it. I will later see what was wrong with my approach.
My approach was to find a pattern: first locate nodes such as 5, 50, 500, and 5000, then observe that the number of added pairs grows like 1 + 2 + 3. The special case is numbers ending in 9, which can then be subtracted. It still feels overcomplicated.
repp(i, 2, n) { if (v[i] != v[i - 1]) { val[cnt] = len; pos_val[cnt] = v[i - 1]; heap.insert(make_pair(-len, cnt)); cnt++; len = 1; } else { len++; } } pos_val[cnt] = v[n]; val[cnt] = len; heap.insert(make_pair(-len, cnt)); for (int i = 1; i <= cnt; i++) { le[i] = i - 1, ri[i] = (i == cnt ? 0 : i + 1); } int ans = 0; int k, j; while (true) { ans++; if (heap.size() == 1) { break; } k = heap.begin()->second, j = heap.begin()->first, heap.erase(heap.begin()); if (pos_val[le[k]] == pos_val[ri[k]]) { int sum = (val[le[k]] + val[ri[k]]); heap.erase(make_pair(-(val[le[k]]), le[k])); heap.erase(make_pair(-(val[ri[k]]), ri[k])); int t = le[k]; val[ri[k]] = 0; del(ri[k]); del(k); val[k] = 0; val[t] = sum; heap.insert(make_pair(-(sum), t)); } else { val[k] = 0; del(k); } } cout << ans << endl; }
For Problem F, I mainly did not know how to move through the string from the front, so my reasoning stalled there.
Ah, a Fenwick tree can do this. Why did I not know that yet?
Oh—binary search works too, with one more logarithmic factor. Given a prefix sum K, find the position whose prefix sum is K; binary search gives two logarithmic factors. A Google interview once asked about a one-log approach.
int n, m; int val[300]; set<int>pos[300]; char v[maxn]; ll num[maxn]; intlowbit(int x) { return x&(-x); } ll getsum(ll x) { ll ans = 0; while (x>0) { ans += num[x]; x -= lowbit(x); } return ans; } ll add(int x, int v) { int up = maxn - 1; while (x <= up) { num[x] += v; x += lowbit(x); } return x; }
intfind_p(int k) { int le = 1, ri = n; while (le < ri) { int mid = (le + ri) / 2; if (getsum(mid) < k) { le = mid + 1; } else { ri = mid; } } return le; }
voidsolve() { sa(n), sa(m); scanf("%s", v + 1); repp(i, 1, n) { pos[v[i]].insert(i); add(i, 1); } repp(i, 1, m) { int le, ri; char op[5]; scanf("%d%d%s", &le, &ri, op); char k = op[0]; le = find_p(le); ri = find_p(ri);
auto p = pos[k].lower_bound(le); while (p != pos[k].end()&&*p <= ri) { add(*p, -1); auto t = p; p++; pos[k].erase(t); } } repp(i, 1, n) { if (getsum(i) - getsum(i - 1)) { printf("%c", v[i]); } } }