#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;
}
};
const int MAX_N = 3e5;
struct AIB2D {
int n;
vector<AIB> aib;
void init( int _n ) {
n = _n;
aib.resize( n + 1 );
for ( int i = 0; i <= n; i++ )
aib[i].clear();
}
void insert( int x, int y ) {
int cx = x;
while ( x > 0 ) {
aib[x].insert( y );
x -= (x & -x);
}
x = cx;
while ( x <= n ) {
aib[x].insert( y );
x += (x & -x);
}
}
void prep() {
for ( int i = 0; i <= n; i++ )
aib[i].prep();
}
void update( int i, int j, int x ) {
while ( i <= n ) {
aib[i].update( j, x );
i += (i & -i);
}
}
int query( int i, int j ) {
int x = 0;
while ( i > 0 ) {
x = aib[i].query( j );
i -= (i & -i);
}
return x;
}
};
struct AIB2D1 {
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_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 ) {
//printf( "erase %d %d %d\n", t, s.l, s.r );
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.init( n + 1 );
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 } );
erasedSegments.insert( 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--;
int l = p->l, r = p->r;
eraseSegment( *p, t );
if ( i > l )
insertSegment( { l, i - 1, t }, t );
if ( i < r )
insertSegment( { i + 1, 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" );
printf( "es\n" );
for ( segment s: es )
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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |