Submission #790163

#TimeUsernameProblemLanguageResultExecution timeMemory
790163GrindMachineStreet Lamps (APIO19_street_lamps)C++17
100 / 100
1405 ms64172 KiB
// Om Namah Shivaya #include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> using namespace std; using namespace __gnu_pbds; template<typename T> using Tree = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>; typedef long long int ll; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; #define fastio ios_base::sync_with_stdio(false); cin.tie(NULL) #define pb push_back #define endl '\n' #define sz(a) a.size() #define setbits(x) __builtin_popcountll(x) #define ff first #define ss second #define conts continue #define ceil2(x, y) ((x + y - 1) / (y)) #define all(a) a.begin(), a.end() #define rall(a) a.rbegin(), a.rend() #define yes cout << "Yes" << endl #define no cout << "No" << endl #define rep(i, n) for(int i = 0; i < n; ++i) #define rep1(i, n) for(int i = 1; i <= n; ++i) #define rev(i, s, e) for(int i = s; i >= e; --i) #define trav(i, a) for(auto &i : a) template<typename T> void amin(T &a, T b) { a = min(a, b); } template<typename T> void amax(T &a, T b) { a = max(a, b); } #ifdef LOCAL #include "debug.h" #else #define debug(x) 42 #endif /* #of moments when everybody in range was 1 1) naive 2) count #of times index has been 1 every time when turning off, add active time of ind add extra active time if ind is active during query time 3) every query is good on some suff find the max time someone in the range is set all queries after this is good use segtree for range max queries 4) can maintain a set of all active 1 segs when toggle, upd set also, store all segs (including non-active) and their active time in total when query, find the sum of active times of all segs [lx,rx] s.t lx <= l <= r <= rx sweepline + bit 5) extend 4) idea? answer queries online find sum of active times of all segs [lx,rx] s.t lx <= l <= r <= rx compressed bit at each node of seg preprocess all compressed bits first, then make updates alternatively, can also use sparse bit (with unordered_map/gp_hash_table) also, add [l,r] contribution from the active set (guys from the active set are not in segs) */ const int MOD = 1e9 + 7; const int N = 3e5 + 5; const int inf1 = int(1e9) + 5; const ll inf2 = ll(1e18) + 5; struct compressed_fenwick { vector<int> vals,tr; int siz = 0; bool prepared = false; int lsb(int x){ return x & -x; } void prepare(){ prepared = true; sort(all(vals)); vals.resize(unique(all(vals))-vals.begin()); siz = sz(vals); tr = vector<int>(siz+1); } void pupd(int i, int v){ if(!prepared){ vals.pb(i); return; } i = lower_bound(all(vals),i) - vals.begin(); i++; for(; i <= siz; i += lsb(i)){ tr[i] += v; } } int get(int i){ int res = 0; for(; i; i -= lsb(i)){ res += tr[i]; } return res; } int suff_sum(int i){ // suff_sum = tot-pref_sum i = lower_bound(all(vals),i)-vals.begin()-1+1; return get(siz) - get(i); } }; template<typename T> struct fenwick { int siz; vector<compressed_fenwick> tree; bool prepared = false; fenwick(int n) { siz = n; tree = vector<compressed_fenwick>(n + 1); } int lsb(int x) { return x & -x; } void prepare(){ prepared = true; rep(i,siz+1){ tree[i].prepare(); } } void pupd(int i, int pos, T v) { while (i <= siz) { tree[i].pupd(pos,v); i += lsb(i); } } T sum(int i, int pos) { T res = 0; while (i) { res += tree[i].suff_sum(pos); i -= lsb(i); } return res; } T query(int l, int r, int pos) { if (l > r) return 0; T res = sum(r,pos) - sum(l-1,pos); return res; } }; void solve(int test_case) { int n,q; cin >> n >> q; vector<int> a(n+5); rep1(i,n){ char ch; cin >> ch; a[i] = ch-'0'; } set<array<int,3>> active; vector<array<int,3>> segs; fenwick<int> fenw(n+5); auto init_active = [&](){ int l = -1; rep1(i,n){ if(!a[i]){ if(l != -1){ active.insert({l,i-1,0}); } l = -1; } else{ if(l == -1){ l = i; } } } if(l != -1){ active.insert({l,n,0}); } }; auto get_seg = [&](int i){ auto it = active.upper_bound({i+1,-1,-1}); if(it == active.begin()) return active.end(); else{ it--; auto [l,r,t] = *it; if(l <= i and r >= i){ return it; } else{ return active.end(); } } }; auto insert_seg = [&](set<array<int,3>>::iterator it, int id){ auto [l,r,t] = *it; segs.pb({l,r,id-t}); fenw.pupd(l,r,id-t); }; init_active(); vector<array<int,3>> queries(q+5); auto oa = a; rep1(id,q){ string t; cin >> t; if(t == "toggle"){ int i; cin >> i; queries[id] = {1,i,-1}; a[i] ^= 1; if(!a[i]){ // unset auto it = get_seg(i); assert(it != active.end()); auto [l,r,t] = *it; insert_seg(it,id); active.erase(it); if(l <= i-1){ active.insert({l,i-1,id}); } if(i+1 <= r){ active.insert({i+1,r,id}); } } else{ // set auto it1 = get_seg(i-1); auto it2 = get_seg(i+1); int l = -1, r = -1; if(it1 != active.end()){ auto curr = *it1; l = curr[0]; insert_seg(it1,id); active.erase(it1); } if(it2 != active.end()){ auto curr = *it2; r = curr[1]; insert_seg(it2,id); active.erase(it2); } if(l != -1 and r != -1){ active.insert({l,r,id}); } else if(l != -1){ active.insert({l,i,id}); } else if(r != -1){ active.insert({i,r,id}); } else{ active.insert({i,i,id}); } } } else{ int l,r; cin >> l >> r; r--; queries[id] = {2,l,r}; } } a = oa; active.clear(); segs.clear(); init_active(); fenw.prepare(); rep1(id,q){ if(queries[id][0] == 1){ int i = queries[id][1]; a[i] ^= 1; if(!a[i]){ // unset auto it = get_seg(i); assert(it != active.end()); auto [l,r,t] = *it; insert_seg(it,id); active.erase(it); if(l <= i-1){ active.insert({l,i-1,id}); } if(i+1 <= r){ active.insert({i+1,r,id}); } } else{ // set auto it1 = get_seg(i-1); auto it2 = get_seg(i+1); int l = -1, r = -1; if(it1 != active.end()){ auto curr = *it1; l = curr[0]; insert_seg(it1,id); active.erase(it1); } if(it2 != active.end()){ auto curr = *it2; r = curr[1]; insert_seg(it2,id); active.erase(it2); } if(l != -1 and r != -1){ active.insert({l,r,id}); } else if(l != -1){ active.insert({l,i,id}); } else if(r != -1){ active.insert({i,r,id}); } else{ active.insert({i,i,id}); } } } else{ int l = queries[id][1], r = queries[id][2]; auto it = get_seg(l); int ans = 0; { auto [lx,rx,t] = *it; if(lx <= l and rx >= r){ ans += id-t; } } ans += fenw.query(1,l,r); /* for(auto [lx,rx,wx] : segs){ if(lx <= l and rx >= r){ ans += wx; } } */ cout << ans << endl; } } } int main() { fastio; int t = 1; // cin >> t; rep1(i, t) { solve(i); } return 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...