Submission #850200

#TimeUsernameProblemLanguageResultExecution timeMemory
850200hngwlogStreet Lamps (APIO19_street_lamps)C++17
80 / 100
5025 ms36424 KiB
#include <bits/stdc++.h> using namespace std; #define fi first #define se second #define _size(x) (int)x.size() #define BIT(i, x) ((x >> i) & 1) #define MASK(n) ((1 << n) - 1) #define REP(i, n) for (int i = 0, _n = (n); i < _n; i++) #define FOR(i, a, b) for (int i = a, _b = (b); i <= _b; i++) #define FORD(i, a, b) for (int i = a, _b = (b); i >= _b; i--) #define FORB1(i, mask) for (int i = mask; i > 0; i ^= i & - i) #define FORB0(i, n, mask) for (int i = ((1 << n) - 1) ^ mask; i > 0; i ^= i & - i) #define FORALL(i, a) for (auto i: a) #define fastio ios_base::sync_with_stdio(0); cin.tie(0); struct queryNode { string type; int id, a, b; }; int n, q; string s; vector<int> a; vector<queryNode> qu; namespace subtask1 { void main() { vector<vector<int>> c(q + 1, vector<int>(n + 1)); FOR(i, 1, n) c[0][i] = a[i] + c[0][i - 1]; REP(i, q) { FOR(j, 1, n) c[i + 1][j] = c[i][j] - c[i][j - 1]; if (i && qu[i - 1].type == "toggle") c[i + 1][qu[i - 1].id] = 1 - c[i + 1][qu[i - 1].id]; FOR(j, 1, n) c[i + 1][j] += c[i + 1][j - 1]; if (qu[i].type == "query") { int a = qu[i].a, b = qu[i].b - 1; int ans = 0; FOR(j, 1, i + 1) ans += (c[j][b] - c[j][a - 1] == b - a + 1); cout << ans << '\n'; } } } } bool checkSub2() { REP(i, q) { if (qu[i].type == "toggle") continue; if (qu[i].b - qu[i].a != 1) return false; } return true; } namespace subtask2 { void main() { vector<int> ans(n + 1), in(n + 1, - 1); FOR(i, 1, n) if (a[i] == 1) in[i] = 1; REP(i, q) { if (i && qu[i - 1].type == "toggle") { int id = qu[i - 1].id; if (!a[id]) { a[id] = 1 - a[id]; in[id] = i + 1; } else { a[id] = 0; ans[id] += (i + 1) - in[id]; in[id] = - 1; } } if (qu[i].type == "query") cout << ans[qu[i].a] + (in[qu[i].a] != - 1 ? i + 1 - in[qu[i].a] + 1 : 0) << '\n'; } } } bool checkSub3() { vector<int> b(n + 1); FOR(i, 1, n) b[i] = a[i]; REP(i, q) { if (qu[i].type == "toggle") { int id = qu[i].id; if (b[id]) return false; b[id] = 1 - b[id]; } } return true; } namespace subtask3 { const int inf = 1e9; struct segTree { vector<int> ST; void init(int n) { ST.resize(4 * n + 4); } void update(int id, int l, int r, int pos, int val) { if (pos < l || r < pos) return ; if (l == r) { ST[id] = val; return ; } int mid = (l + r) / 2; update(id * 2, l, mid, pos, val); update(id * 2 + 1, mid + 1, r, pos, val); ST[id] = max(ST[id * 2], ST[id * 2 + 1]); } int get(int id, int l, int r, int u, int v) { if (r < u || v < l) return 0; if (u <= l && r <= v) return ST[id]; int mid = (l + r) / 2; return max(get(id * 2, l, mid, u, v), get(id * 2 + 1, mid + 1, r, u, v)); } } st; void main() { st.init(n); FOR(i, 1, n) { if (a[i]) st.update(1, 1, n, i, 1); else st.update(1, 1, n, i, inf); } REP(i, q) { if (qu[i].type == "toggle") { int id = qu[i].id; st.update(1, 1, n, id, i + 2); } if (qu[i].type == "query") { int a = qu[i].a, b = qu[i].b - 1; int value = st.get(1, 1, n, a, b); if (value == inf) cout << 0 << '\n'; else cout << i + 1 - value + 1 << '\n'; } } } } bool checkSub4() { int cnt = 0; REP(i, q) { if (qu[i].type == "toggle" && cnt) return false; cnt += (qu[i].type == "query"); } return true; } namespace subtask4 { struct fenTree { int n; vector<int> bit; void init(int sz) { bit.resize(sz + 1); n = sz; } void update(int pos, int val) { while (pos <= n) { bit[pos] += val; pos += pos & - pos; } } int get(int pos) { int res = 0; while (pos) { res += bit[pos]; pos -= pos & - pos; } return res; } } ft; void main() { map<pair<int, int>, int> in; set<int> st; int pos = - 1; FOR(i, 1, n) { if (!a[i]) { if (pos != - 1) { in[{pos, i - 1}] = 1; pos = - 1; } st.insert(i); } if (pos == - 1 && a[i]) pos = i; } if (pos) in[{pos, n}] = 1; vector<pair<pair<int, int>, int>> g; FOR(i, 1, q - 1) { if (qu[i - 1].type == "toggle") { int id = qu[i - 1].id; auto it = st.lower_bound(id); int l = - 1, r = - 1; if (it == st.end()) r = n; else r = *it - 1; if (it == st.begin()) l = 1; else { it--; l = *it + 1; } if (a[id]) { g.push_back({{l, r}, i - in[{l, r}] + 1}); in.erase({l, r}); if (l <= id - 1) in[{l, id - 1}] = i + 1; if (id + 1 <= r) in[{id + 1, r}] = i + 1; st.insert(id); } else { it = st.upper_bound(id); if (it == st.end()) r = n; else r = *it - 1; if (l <= id - 1) { g.push_back({{l, id - 1}, i - in[{l, id - 1}] + 1}); in.erase({l, id - 1}); } if (id + 1 <= r) { g.push_back({{id + 1, r}, i - in[{id + 1, r}] + 1}); in.erase({id + 1, r}); } in[{l, r}] = i + 1; st.erase(id); } a[id] = 1 - a[id]; } if (qu[i].type == "query") break; } sort(g.begin(), g.end(), [&] (const pair<pair<int, int>, int> a, pair<pair<int, int>, int> b) { return a.fi.fi < b.fi.fi; }); vector<int> ask; REP(i, q) { if (qu[i].type == "toggle") continue; ask.push_back(i); } sort(ask.begin(), ask.end(), [&] (const int i, int j) { return qu[i].a < qu[j].a; }); vector<int> ans(q); ft.init(n); int i = 0; FORALL(id, ask) { while (i < _size(g) && g[i].fi.fi <= qu[id].a) { ft.update(g[i].fi.se, g[i].se); i++; } ans[id] += ft.get(n) - ft.get(qu[id].b - 2); } vector<int> vtx; FOR(i, 1, n) if (!a[i]) vtx.push_back(i); int cnt = 0; REP(i, q) { if (qu[i].type == "toggle") continue; if (!_size(vtx)) cout << ans[i] + i + 1 - in[{1, n}] + 1 << '\n'; else { pos = lower_bound(vtx.begin(), vtx.end(), qu[i].a) - vtx.begin(); if (pos == _size(vtx) || vtx[pos] > qu[i].b - 1) { int l = (pos > 0 ? vtx[pos - 1] + 1 : 1); int r = (pos == _size(vtx) ? n : vtx[pos] - 1); cout << ans[i] + i + 1 - in[{l, r}] + 1 << '\n'; } else cout << ans[i] << '\n'; } } } } namespace subtask5 { struct fenTree { vector<int> bit; void reset(int sz) { n = sz; bit.clear(); bit.resize(n + 1); } void update(int pos, int val) { while (pos <= n) { bit[pos] += val; pos += pos & - pos; } } int get(int pos) { int res = 0; while (pos) { res += bit[pos]; pos -= pos & - pos; } return res; } } ft; void main() { /*** chia thanh sqrt(q) block duyet trong block neu la "toggle" thi update nhu bthg con khong duyet lai cac doan moi them */ map<pair<int, int>, int> in; vector<pair<pair<int, int>, int>> g; set<int> st; int pos = - 1; FOR(i, 1, n) { if (!a[i]) { if (pos != - 1) { in[{pos, i - 1}] = 1; pos = - 1; } st.insert(i); } if (pos == - 1 && a[i]) pos = i; } if (pos) in[{pos, n}] = 1; int blockSz = 2000; int cnt = q / blockSz + (q % blockSz ? 1 : 0); vector<int> ans(q); REP(t, cnt) { int l = t * blockSz, r = min(q - 1, (t + 1) * blockSz - 1); vector<int> ask; FOR(i, l, r) if (qu[i].type == "query") ask.push_back(i); sort(ask.begin(), ask.end(), [&] (const int i, int j) { return qu[i].a < qu[j].a; }); sort(g.begin(), g.end(), [&] (const pair<pair<int, int>, int> a, pair<pair<int, int>, int> b) { return a.fi.fi < b.fi.fi; }); ft.reset(n); int j = 0; FORALL(id, ask) { while (j < _size(g) && g[j].fi.fi <= qu[id].a) { ft.update(n - g[j].fi.se + 1, g[j].se); j++; } vector<int> sav_vtx; vector<pair<pair<int, int>, int>> sav_in, _g; FOR(i, l, id) { if (qu[i].type == "query") continue; int _id = qu[i].id; auto it = st.lower_bound(_id); int l = - 1, r = - 1; if (it == st.end()) r = n; else r = *it - 1; if (it == st.begin()) l = 1; else { it--; l = *it + 1; } if (a[_id]) { _g.push_back({{l, r}, i + 1 - in[{l, r}] + 1}); sav_in.push_back({{l, r}, - in[{l, r}]}); in.erase({l, r}); if (l <= _id - 1) { in[{l, _id - 1}] = i + 2; sav_in.push_back({{l, _id - 1}, i + 1}); } if (_id + 1 <= r) { in[{_id + 1, r}] = i + 2; sav_in.push_back({{_id + 1, r}, i + 1}); } st.insert(_id); sav_vtx.push_back(_id); } else { it = st.upper_bound(_id); if (it == st.end()) r = n; else r = *it - 1; if (l <= _id - 1) { _g.push_back({{l, _id - 1}, i + 1 - in[{l, _id - 1}] + 1}); sav_in.push_back({{l, _id - 1}, - in[{l, _id - 1}]}); in.erase({l, _id - 1}); } if (id + 1 <= r) { _g.push_back({{_id + 1, r}, i + 1 - in[{_id + 1, r}] + 1}); sav_in.push_back({{_id + 1, r}, - in[{_id + 1, r}]}); in.erase({_id + 1, r}); } in[{l, r}] = i + 2; sav_in.push_back({{l, r}, i + 2}); st.erase(_id); sav_vtx.push_back(- _id); } a[_id] = 1 - a[_id]; } int res = ft.get(n - (qu[id].b - 1) + 1); FORALL(e, _g) if (e.fi.fi <= qu[id].a && e.fi.se >= qu[id].b - 1) res += e.se; auto it = st.lower_bound(qu[id].a); if (it == st.end() || *it > qu[id].b - 1) { int pos = - 1; if (it == st.begin()) pos = 1; else { it--; pos = *it + 1; it++; } res += id + 1 - in[{pos, *it - 1}] + 1; } ans[id] = res; FORD(i, _size(sav_in) - 1, 0) { if (sav_in[i].se > 0) in.erase(sav_in[i].fi); else in[sav_in[i].fi] = - sav_in[i].se; } FORD(i, _size(sav_vtx) - 1, 0) { int pos = sav_vtx[i]; a[pos] = 1 - a[pos]; if (pos < 0) st.insert(- pos); else st.erase(pos); } } FOR(i, l, r) { if (qu[i].type == "query") continue; int id = qu[i].id; auto it = st.lower_bound(id); int l = - 1, r = - 1; if (it == st.end()) r = n; else r = *it - 1; if (it == st.begin()) l = 1; else { it--; l = *it + 1; } if (a[id]) { g.push_back({{l, r}, i + 1 - in[{l, r}] + 1}); in.erase({l, r}); if (l <= id - 1) in[{l, id - 1}] = i + 2; if (id + 1 <= r) in[{id + 1, r}] = i + 2; st.insert(id); } else { it = st.upper_bound(id); if (it == st.end()) r = n; else r = *it - 1; if (l <= id - 1) { g.push_back({{l, id - 1}, i + 1 - in[{l, id - 1}] + 1}); in.erase({l, id - 1}); } if (id + 1 <= r) { g.push_back({{id + 1, r}, i + 1 - in[{id + 1, r}] + 1}); in.erase({id + 1, r}); } in[{l, r}] = i + 2; st.erase(id); } a[id] = 1 - a[id]; } } REP(i, q) if (qu[i].type == "query") cout << ans[i] << '\n'; } } int main() { fastio; cin >> n >> q; cin >> s; a.resize(n + 1); FOR(i, 1, n) a[i] = s[i - 1] - '0'; qu.resize(q); REP(i, q) { cin >> qu[i].type; if (qu[i].type == "toggle") cin >> qu[i].id; else cin >> qu[i].a >> qu[i].b; } if (n <= 100 && q <= 100) subtask1::main(); else if (checkSub2()) subtask2::main(); else if (checkSub3()) subtask3::main(); else if (checkSub4()) subtask4::main(); else subtask5::main(); return 0; }

Compilation message (stderr)

street_lamps.cpp: In function 'void subtask4::main()':
street_lamps.cpp:268:13: warning: unused variable 'cnt' [-Wunused-variable]
  268 |         int cnt = 0;
      |             ^~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...