Submission #729762

#TimeUsernameProblemLanguageResultExecution timeMemory
729762danikoynov가로등 (APIO19_street_lamps)C++14
0 / 100
4144 ms524288 KiB
#include<bits/stdc++.h> #define endl '\n' using namespace std; typedef long long ll; void speed() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); } struct interval { int left, right, in_time; interval(int _left, int _right, int _in_time) { left = _left; right = _right; in_time = _in_time; } bool operator < (const interval &it) const { return left < it.left; } }; const int maxn = 3e5 + 10; struct base_query { string type; int x, a, b; } base_ask[maxn]; int n, q; char c[maxn], cs[maxn]; void input() { cin >> n >> q; n ++; for (int i = 1; i < n; i ++) cin >> c[i], cs[i] = c[i]; for (int i = 1; i <= q; i ++) { cin >> base_ask[i].type; if (base_ask[i].type == "query") { cin >> base_ask[i].a >> base_ask[i].b; } else { cin >> base_ask[i].x; } } } set < pair < int, int > > available; void create_intervals() { set < interval > st; int beg = 1; for (int i = 1; i < n; i ++) { if (c[i] == '0') { ///cout << beg << " -- " << i << endl; st.insert(interval(beg, i, 0)); available.insert({beg, i}); beg = i + 1; } } st.insert(interval(beg, n, 0)); available.insert({beg, n}); for (int i = 1; i <= q; i ++) { if (base_ask[i].type == "toggle") { int pos = base_ask[i].x; if (c[pos] == '0') { c[pos] = '1'; set < interval > :: iterator aft_it = st.lower_bound(interval(pos + 1, pos + 1, -1)); set < interval > :: iterator bef_it = prev(aft_it); interval bef = *bef_it; interval aft = *aft_it; interval cur(bef.left, aft.right, i); st.erase(bef); st.erase(aft); st.insert(cur); available.insert({cur.left, cur.right}); } else { c[pos] = '0'; set < interval > :: iterator cur_it = prev(st.lower_bound(interval(pos + 1, pos + 1, -1))); interval cur = *cur_it; interval bef(cur.left, pos, i); interval aft(pos, cur.right, i); st.erase(cur); st.insert(bef); st.insert(aft); available.insert({bef.left, bef.right}); available.insert({aft.left, aft.right}); } } } //for (pair < int, int > cur : available) // cout << cur.first << " : " << cur.second << endl; } const int smalln = 110; ///int act[smalln][smalln], act_time[smalln][smalln], sum[smalln][smalln]; struct node { int act_cnt, sum; node(int _act_cnt = 0, int _sum = 0) { act_cnt = _sum; sum = _sum; } }; node merge_node(node bef, node aft) { node cur; cur.act_cnt = bef.act_cnt + aft.act_cnt; cur.sum = bef.sum + aft.sum; return cur; } struct segment_tree { vector < node > tree; int n; segment_tree() {}; segment_tree(int _n) { n = _n; tree.resize(4 * n); } void update_toggle(int root, int left, int right, int pos) { if (left == right) { tree[root].act_cnt ++; tree[root].act_cnt %= 2; return; } int mid = (left + right) / 2; if (pos <= mid) update_toggle(root * 2, left, mid, pos); else update_toggle(root * 2 + 1, mid + 1, right, pos); tree[root] = merge_node(tree[root * 2], tree[root * 2 + 1]); } void update_add(int root, int left, int right, int pos, int val) { if (left == right) { tree[root].sum += val; return; } int mid = (left + right) / 2; if (pos <= mid) update_add(root * 2, left, mid, pos, val); else update_add(root * 2 + 1, mid + 1, right, pos, val); tree[root] = merge_node(tree[root * 2], tree[root * 2 + 1]); } node query_range(int root, int left, int right, int qleft, int qright) { if (left > qright || right < qleft) return node(); if (left >= qleft && right <= qright) return tree[root]; int mid = (left + right) / 2; return merge_node(query_range(root * 2, left, mid, qleft, qright), query_range(root * 2 + 1, mid + 1, right, qleft, qright)); } void toggle(int pos) { update_toggle(1, 0, n - 1, pos); } void add(int pos, int val) { update_add(1, 0, n - 1, pos, val); } node query(int left, int right) { return query_range(1, 0, n - 1, left, right); } }; segment_tree seg[4 * maxn]; vector < pair < int, int > > tree[4 * maxn], values[maxn]; map < int, int > act_time[maxn], act[maxn]; int lower_bound_simulate(int root, pair < int, int > cur) { int lf = 0, rf = tree[root].size() - 1; while(lf <= rf) { int mf = (lf + rf) / 2; if (tree[root][mf].second < cur.second) lf = mf + 1; else if (tree[root][mf].second > cur.second) rf = mf - 1; else { if (tree[root][mf].first < cur.first) lf = mf + 1; else rf = mf - 1; } } return lf; } void toggle_node(int root, pair < int, int > cur, int cur_time) { int lf = lower_bound_simulate(root, cur); seg[root].toggle(lf); if (act[cur.first][cur.second] == 0) { ///cout << "toggle " << root << " " << cur.first << " " << cur.second << endl; seg[root].add(lf, cur_time - act_time[cur.first][cur.second]); } } void toggle(int root, int left, int right, pair < int, int > cur, int cur_time) { toggle_node(root, cur, cur_time); if (left == right) return; int mid = (left + right) / 2; if (cur.first <= mid) toggle(root * 2, left, mid, cur, cur_time); else toggle(root * 2 + 1, mid + 1, right, cur, cur_time); } void update_interval(interval cur, int cur_time) { if (act[cur.left][cur.right] == 0) { act[cur.left][cur.right] = 1; } else { act[cur.left][cur.right] = 0; } ///cout << "update " << cur.left << " " << cur.right << endl; toggle(1, 1, n, {cur.left, cur.right}, cur_time); if (act[cur.left][cur.right] == 1) act_time[cur.left][cur.right] = cur_time; } int query(int root, int left, int right, pair < int, int > val, int cur_time) { if (left > val.first) return 0; if (right <= val.first) { ///cout << root << " : " << left << " : " << right << " : " << val.first << " : " << val.second << endl; int lf = lower_bound_simulate(root, {-1, val.second}); node cur = seg[root].query(lf, (int)(tree[root].size()) - 1); int ans = cur.sum; ///cout << "here " << lf << " " << tree[root][lf].second << endl; return ans; } int mid = (left + right) / 2; return query(root * 2, left, mid, val, cur_time) + query(root * 2 + 1, mid + 1, right, val, cur_time); } void conquer(int root, int lf, int rf) { int left = 0, right = 0; while(left < tree[lf].size() && right < tree[rf].size()) { if (tree[lf][left].second < tree[rf][right].second) { tree[root].push_back(tree[lf][left ++]); } else if (tree[lf][left].second > tree[rf][right].second) { tree[root].push_back(tree[rf][right ++]); } else if (tree[lf][left].first < tree[rf][right].first) { tree[root].push_back(tree[lf][left ++]); } else if (tree[lf][left].first > tree[rf][right].first) { tree[root].push_back(tree[rf][right ++]); } } while(left < tree[lf].size()) tree[root].push_back(tree[lf][left ++]); while(right < tree[rf].size()) tree[root].push_back(tree[rf][right ++]); seg[root] = segment_tree(tree[root].size()); } void divide(int root, int left, int right) { if (left == right) { tree[root] = values[left]; seg[root] = segment_tree(tree[root].size()); return; } int mid = (left + right) / 2; divide(root * 2, left, mid); divide(root * 2 + 1, mid + 1, right); conquer(root, root * 2, root * 2 + 1); } void build_trees() { for (pair < int, int > cur : available) { values[cur.first].push_back(cur); } divide(1, 1, n); } void simulate() { set < interval > st; int beg = 1; for (int i = 1; i < n; i ++) { c[i] = cs[i]; if (c[i] == '0') { st.insert(interval(beg, i, 0)); update_interval(interval(beg, i, -1), 0); beg = i + 1; } } st.insert(interval(beg, n, 0)); update_interval(interval(beg, n, -1), 0); ///cout << "--------------" << endl; for (int i = 1; i <= q; i ++) { if (base_ask[i].type == "toggle") { ///cout << "toggle" << endl; int pos = base_ask[i].x; if (c[pos] == '0') { c[pos] = '1'; set < interval > :: iterator aft_it = st.lower_bound(interval(pos + 1, pos + 1, -1)); set < interval > :: iterator bef_it = prev(aft_it); interval bef = *bef_it; interval aft = *aft_it; interval cur(bef.left, aft.right, i); update_interval(bef, i); update_interval(aft, i); update_interval(cur, i); st.erase(bef); st.erase(aft); st.insert(cur); available.insert({cur.left, cur.right}); } else { c[pos] = '0'; set < interval > :: iterator cur_it = prev(st.lower_bound(interval(pos + 1, pos + 1, -1))); interval cur = *cur_it; interval bef(cur.left, pos, i); interval aft(pos + 1, cur.right, i); ///cout << " ::: " << bef.left << " " << bef.right << endl; st.erase(cur); st.insert(bef); st.insert(aft); update_interval(bef, i); update_interval(aft, i); update_interval(cur, i); available.insert({bef.left, bef.right}); available.insert({aft.left, aft.right}); } } else { int ans = query(1, 1, n, {base_ask[i].a, base_ask[i].b}, i); for (int l = 1; l <= base_ask[i].a; l ++) for (int r = base_ask[i].b; r <= n; r ++) { ///ans = ans + sum[l][r]; ///cout << l << " -- " << r << " " << act[l][r] << endl; if (act[l][r]) { ///cout << l << " " << r << " " << act_time[l][r] << endl; ans = ans + i - act_time[l][r]; } } cout << ans << endl; } } //for (pair < int, int > cur : available) // cout << cur.first << " : " << cur.second << endl; } void solve() { input(); create_intervals(); build_trees(); simulate(); } int main() { solve(); return 0; } /** 5 3 11011 toggle 2 toggle 1 query 1 2 */

Compilation message (stderr)

street_lamps.cpp: In function 'void conquer(int, int, int)':
street_lamps.cpp:309:16: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  309 |     while(left < tree[lf].size() && right < tree[rf].size())
      |           ~~~~~^~~~~~~~~~~~~~~~~
street_lamps.cpp:309:43: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  309 |     while(left < tree[lf].size() && right < tree[rf].size())
      |                                     ~~~~~~^~~~~~~~~~~~~~~~~
street_lamps.cpp:329:16: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  329 |     while(left < tree[lf].size())
      |           ~~~~~^~~~~~~~~~~~~~~~~
street_lamps.cpp:332:17: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  332 |     while(right < tree[rf].size())
      |           ~~~~~~^~~~~~~~~~~~~~~~~
#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...