Submission #1124004

#TimeUsernameProblemLanguageResultExecution timeMemory
1124004LucaIlieFire (JOI20_ho_t5)C++20
1 / 100
1099 ms58824 KiB
#include <bits/stdc++.h>

using namespace std;

struct query {
    int t, l, r;
    long long ans;
};

struct AIB {
    int n;
    vector<long long> aib;

    void init( int _n ) {
        n = _n;
        aib.resize( n + 1 );
    }

    void update( int i, long long x ) {
        while ( i <= n ) {
            aib[i] += x;
            i += (i & -i);
        }
    }

    long long query( int i ) {
        long long sum = 0;
        while ( i > 0 ) {
            sum += aib[i];
            i -= (i & -i);
        }
        return sum;
    }
};

const int MAX_N = 2e5;
const int MAX_Q = 2e5;
int n;
int a[MAX_N + 1], leftt[MAX_N + 1], rightt[MAX_N + 1];
vector<int> queriesByTime[MAX_N + 1];
vector<int> stopIncreasingR[MAX_N + 1], startDecreasingL[MAX_N + 1], stopAll[MAX_N + 1];
query queries[MAX_Q];
set<int> increasingR, constantR, constantL, decreasingL;
AIB sumIncreasingR, sumIncreasingRI;
AIB sumConstantR, sumConstantRI;
AIB sumConstantL, sumConstantLI;
AIB sumDecreasingL, sumDecreasingLI;

void toggleIncreasingR( int i ) {
    if ( increasingR.find( i ) == increasingR.end() ) {
        increasingR.insert( i );
        sumIncreasingR.update( i, a[i] );
        sumIncreasingRI.update( i, (long long)a[i] * i );
    } else {
        increasingR.erase( i );
        sumIncreasingR.update( i, -a[i] );
        sumIncreasingRI.update( i, -(long long)a[i] * i );
    }
}

void toggleConstantR( int i ) {
    if ( constantR.find( i ) == constantR.end() ) {
        constantR.insert( i );
        sumConstantR.update( i, a[i] );
        sumConstantRI.update( i, (long long)a[i] * i );
    } else {
        constantR.erase( i );
        sumConstantR.update( i, -a[i] );
        sumConstantRI.update( i, -(long long)a[i] * i );
    }
}

void toggleConstantL( int i ) {
    if ( constantL.find( i ) == constantL.end() ) {
        constantL.insert( i );
        sumConstantL.update( i, a[i] );
        sumConstantLI.update( i, (long long)a[i] * i );
    } else {
        constantL.erase( i );
        sumConstantL.update( i, -a[i] );
        sumConstantLI.update( i, -(long long)a[i] * i );
    }
}

void toggleDecreasingL( int i ) {
    if ( decreasingL.find( i ) == decreasingL.end() ) {
        decreasingL.insert( i );
        sumDecreasingL.update( i, a[i] );
        sumDecreasingLI.update( i, (long long)a[i] * i );
    } else {
        decreasingL.erase( i );
        sumDecreasingL.update( i, -a[i] );
        sumDecreasingLI.update( i, -(long long)a[i] * i );
    }
}

long long handleIncreasingR( int t, int p ) {
    auto ptr = increasingR.upper_bound( p - t );
    int pos = (ptr == increasingR.end() ? n + 1 : *ptr);
    long long sum = sumIncreasingRI.query( pos - 1 ) + sumIncreasingR.query( pos - 1 ) * t + (sumIncreasingR.query( n ) - sumIncreasingR.query( pos - 1 )) * p;
    return sum;
}

long long handleConstantR( int t, int p ) {
    long long sum = 0;
    for ( int i: constantR )
        sum += (long long)min( rightt[i] - 1, p ) * a[i];
    return sum;
}

long long handleConstantL( int t, int p ) {
    long long sum = 0;
    for ( int i: constantL )
        sum -= (long long)min( i - 1, p ) * a[i];
    return sum;
}

long long handleDecreasingL( int t, int p ) {
    long long sum = 0;
    for ( int i: decreasingL )
        sum -= (long long)min( t + leftt[i], p ) * a[i];
    return sum;
}

long long getSumPrefix( int t, int p ) {
    //printf( "%d %d\n", t, p );
    long long sum = 0;
    sum += handleIncreasingR( t, p );
    sum += handleConstantR( t, p );
    sum += handleConstantL( t, p );
    sum += handleDecreasingL( t, p );
    return sum;
}

int main() {
    int q;

    cin >> n >> q;
    for ( int i = 1; i <= n; i++ )
        cin >> a[i];
    for ( int i = 0; i < q; i++ ) {
        cin >> queries[i].t >> queries[i].l >> queries[i].r;
        queriesByTime[queries[i].t].push_back( i );
    }

    vector<int> stack;
    for ( int i = 1; i <= n; i++ ) {
        while ( !stack.empty() && a[i] > a[stack.back()] )
            stack.pop_back();
        if ( !stack.empty() )
            leftt[i] = stack.back();
        else
            leftt[i] = -(n + 1);
        stack.push_back( i );
    }
    while ( !stack.empty() )
        stack.pop_back();
    for ( int i = n; i >= 1; i-- ) {
        while ( !stack.empty() && a[i] >= a[stack.back()] )
            stack.pop_back();
        if ( !stack.empty() )
            rightt[i] = stack.back();
        else
            rightt[i] = (n + 1);
        stack.push_back( i );
    }

    sumIncreasingR.init( n );
    sumIncreasingRI.init( n );
    for ( int i = 1; i <= n; i++ ) {
        int goDown = i - leftt[i], goIncreasing = rightt[i] - i;
        toggleIncreasingR( i );
        toggleConstantL( i );
        stopIncreasingR[goIncreasing].push_back( i );
        startDecreasingL[goDown].push_back( i );
        stopAll[goDown + goIncreasing - 1].push_back( i );
    }

    for ( int t = 1; t <= n; t++ ) {
        for ( int i: stopIncreasingR[t] ) {
            toggleIncreasingR( i );
            toggleConstantR( i );
        }
        for ( int i: startDecreasingL[t] ) {
            toggleConstantL( i );
            toggleDecreasingL( i );
        }
        for ( int i: stopAll[t] ) {
            toggleConstantR( i );
            toggleDecreasingL( i );
        }

        /*printf( "timp\n" );
        for ( int i: increasingR )
            printf( "%d ", i );
        printf( "\n" );
        for ( int i: constantR )
            printf( "%d ", i );
        printf( "\n" );
        for ( int i: constantL )
            printf( "%d ", i );
        printf( "\n" );
        for ( int i: decreasingL )
            printf( "%d ", i );
        printf( "\n\n" );*/

        for ( int i: queriesByTime[t] ) {
            //printf( "query\n" );
            queries[i].ans = getSumPrefix( t, queries[i].r ) - getSumPrefix( t, queries[i].l - 1 );
        }
    }

    for ( int i = 0; i < q; i++ )
        cout << queries[i].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...