Submission #1126000

#TimeUsernameProblemLanguageResultExecution timeMemory
1126000LucaIlieStreet Lamps (APIO19_street_lamps)C++20
0 / 100
330 ms56068 KiB
#include <bits/stdc++.h> using namespace std; struct segment { int l, r, t; bool operator < ( const segment &s ) const { return l < s.l; } }; struct query { int l, r; }; struct AIB { int n; vector<int> aib, pos; void clear() { aib.clear(); pos.clear(); pos.push_back( -1 ); } void insert( int x ) { pos.push_back( x ); } void prep() { sort( pos.begin(), pos.end()); pos.resize( unique( pos.begin(), pos.end()) - pos.begin()); n = pos.size(); aib.resize( n ); } void update( int i, int x ) { int l = 0, r = n; while ( r - l > 1 ) { int mid = (l + r) / 2; if ( pos[mid] < i ) l = mid; else r = mid; } i = r; while ( i < n ) { aib[i] += x; i += (i & -i); } } int query( int i ) { if ( i < 0 ) return 0; int l = 0, r = n; while ( r - l > 1 ) { int mid = (l + r) / 2; if ( pos[mid] > i ) r = mid; else l = mid; } i = l; int x = 0; while ( i > 0 ) { x += aib[i]; i -= (i & -i); } return x; } }; struct AIB2D { int n; vector<AIB> aib; vector<pair<int, int>> v; vector<int> pos; vector<vector<int>> pos2; void clear() { aib.clear(); pos.clear(); pos.push_back( -1 ); v.clear(); pos2.clear(); } void insert( int x, int y ) { v.push_back( { x, y } ); pos.push_back( x ); } void prep() { sort( pos.begin(), pos.end() ); sort( v.begin(), v.end() ); pos.resize( unique( pos.begin(), pos.end()) - pos.begin() ); n = pos.size(); aib.resize( n ); pos2.resize( n ); int j = 0; for ( int i = 0; i < n; i++ ) { aib[i].clear(); while ( j < v.size() && v[j].first < pos[i] ) j++; while ( j < v.size() && v[j].first == pos[i] ) { pos2[i].push_back( v[j].second ); j++; } } for ( int i = 1; i < n; i++ ) { int x = i; while ( x < n ) { for ( int y: pos2[x] ) aib[x].insert( y ); x += (x & -x); } } for ( int i = 0; i < n; i++ ) aib[i].prep(); } void update( int i, int j, int x ) { int l = 0, r = n; while ( r - l > 1 ) { int mid = (l + r) / 2; if ( pos[mid] < i ) l = mid; else r = mid; } i = r; while ( i < n ) { aib[i].update( j, x ); i += (i & -i); } } int query( int i, int j ) { if ( i < 0 || j < 0 ) return 0; int l = 0, r = n; while ( r - l > 1 ) { int mid = (l + r) / 2; if ( pos[mid] > i ) r = mid; else l = mid; } i = l; int x = 0; while ( i > 0 ) { x = aib[i].query( j ); i -= (i & -i); } return x; } }; const int MAX_N = 3e5; const int MAX_Q = 3e5; int n; bool on[MAX_N]; vector<segment> insertSegments[MAX_Q + 1], eraseSegments[MAX_Q + 1]; vector<query> queries[MAX_Q + 1]; set<segment> activeSegments; AIB2D erasedSegments; void eraseSegment( segment s, int t ) { activeSegments.erase( s ); erasedSegments.insert( s.l, s.l ); erasedSegments.insert( s.l, s.r + 1 ); erasedSegments.insert( s.r + 1, s.l ); erasedSegments.insert( s.r + 1, s.r + 1 ); eraseSegments[t].push_back( s ); } void insertSegment( segment s, int t ) { activeSegments.insert( s ); insertSegments[t].push_back( s ); } int main() { cin.tie( nullptr ); cout.tie( nullptr ); ios_base::sync_with_stdio( false ); int q; cin >> n >> q; for ( int i = 1; i <= n; i++ ) { char ch; cin >> ch; on[i] = (ch - '0'); } erasedSegments.clear(); for ( int i = 1; i <= n; i++ ) { if ( !on[i] ) continue; int j = i; while ( j <= n && on[j] ) j++; insertSegment( { i, j - 1, 0 }, 0 ); i = j - 1; } for ( int t = 1; t <= q; t++ ) { string type; cin >> type; if ( type == "query" ) { int l, r; cin >> l >> r; r--; queries[t].push_back( { l, r } ); } else { int i; cin >> i; if ( !on[i] ) { on[i] = true; int l = i, r = i; if ( on[i - 1] ) { auto p = activeSegments.lower_bound( { i, i, i } ); p--; l = p->l; eraseSegment( *p, t ); } if ( on[i + 1] ) { auto p = activeSegments.lower_bound( { i, i, i } ); r = p->r; eraseSegment( *p, t ); } insertSegment( { l, r, t }, t ); } else { on[i] = false; auto p = activeSegments.upper_bound( { i, i, i } ); p--; eraseSegment( *p, t ); insertSegment( { p->l, i - 1, t }, t ); insertSegment( { i + 1, p->r, t }, t ); } } } erasedSegments.prep(); activeSegments.clear(); for ( int t = 0; t <= q; t++ ) { for ( segment s: eraseSegments[t] ) { activeSegments.erase( s ); erasedSegments.update( s.l, s.l, t - s.t ); erasedSegments.update( s.l, s.r + 1, -(t - s.t) ); erasedSegments.update( s.r + 1, s.l, -(t - s.t) ); erasedSegments.update( s.r + 1, s.r + 1, t - s.t ); //printf( "UPD %d %d %d\n", s.l, s.r, t - s.t ); } for ( segment s: insertSegments[t] ) activeSegments.insert( s ); /*printf( "TIME %d\n", t ); for ( segment s: activeSegments ) printf( "%d %d %d\n", s.l, s.r, s.t ); printf( "\n" );*/ for ( query q: queries[t] ) { int ans = erasedSegments.query( q.l, q.r ); auto p = activeSegments.upper_bound( { q.l, q.l, q.l } ); if ( p != activeSegments.begin() ) { p--; if ( p->l <= q.l && q.r <= p->r ) ans += t - p->t; } cout << ans << "\n"; } } 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...