Submission #790166

#TimeUsernameProblemLanguageResultExecution timeMemory
790166GrindMachineStreet Lamps (APIO19_street_lamps)C++17
100 / 100
1959 ms220672 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 sparse_fenwick{ gp_hash_table<int,int> tr; int lsb(int x) { return x & -x; } void pupd(int i, int v){ for(; i < N; i += lsb(i)){ tr[i] += v; } } int sum(int i){ int res = 0; for(; i; i -= lsb(i)){ if(tr.find(i) != tr.end()){ res += tr[i]; } } return res; } int query(int l, int r){ if(l > r) return 0; return sum(r) - sum(l-1); } }; template<typename T> struct fenwick { int siz; vector<sparse_fenwick> tree; fenwick(int n) { siz = n; tree = vector<sparse_fenwick>(n + 1); } int lsb(int x) { return x & -x; } 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].query(pos,N-1); 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; { 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(); } } }; fenwick<int> fenw(n+5); 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); }; rep1(id,q){ string t; cin >> t; if(t == "toggle"){ int i; cin >> i; 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--; 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...