Submission #1126011

#TimeUsernameProblemLanguageResultExecution timeMemory
1126011LucaIlieStreet Lamps (APIO19_street_lamps)C++20
20 / 100
5098 ms181448 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 ) {
    //printf( "erase %d %d %d\n", t, s.l, s.r );
    activeSegments.insert( s );
    insertSegments[t].push_back( s );
}

vector<segment> es;

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 } );
            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 );
            es.push_back( { s.l, s.r, 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 = 0;
            for ( segment s: es ) {
                if ( s.l <= q.l && q.r <= s.r )
                    ans += s.t;
            }
            //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...