Submission #884363

#TimeUsernameProblemLanguageResultExecution timeMemory
884363LucaIlieSprinkler (JOI22_sprinkler)C++17
100 / 100
3316 ms209832 KiB
#include <bits/stdc++.h>

using namespace std;

struct update {
    int v, g, d, x, t;
};

struct query {
    int v, g, t;
};

const int MAX_N = 2e5;
const int MAX_AIB = MAX_N + 1;
const int MAX_Q = 4e5;
int n, l;
bool vis[MAX_N + 1];
int h[MAX_N + 1], ans[MAX_Q], sz[MAX_N + 1], depth[MAX_N + 1];
vector<int> edges[MAX_N + 1];
vector<update> updatesV[MAX_N + 1], updates;
vector<query> queriesV[MAX_N + 1], queries;

struct AIB {
    unordered_map<int, int> aib[MAX_AIB + 1];
    vector<int> changes;
    int size1, size2;

    void init( int _size1, int _size2 ) {
        size1 = _size1, size2 = _size2;
        for ( int p: changes )
            aib[p].clear();
        changes.clear();
    }

    void update( int i, int j, int x ) {
        while ( i <= size1 ) {
            int p = j;
            while ( p <= size2 ) {
                if ( aib[i].find( p ) == aib[i].end() )
                    aib[i][p] = 1;
                aib[i][p] = (long long)aib[i][p] * x % l;
                p += (p & -p);
            }
            changes.push_back( i );
            i += (i & -i);
        }
    }

    int query( int i, int j ) {
        int ans = 1;
        while ( i > 0 ) {
            int p = j;
            while ( p > 0 ) {
                if ( aib[i].find( p ) != aib[i].end() )
                    ans = (long long)ans * aib[i][p] % l;
                p -= (p & -p);
            }
            i -= (i & -i);
        }
        return ans;
    }
} aibNI, aibII;

int lgPut( int x, int n ) {
    if ( n == 0 )
        return 1;

    int p = lgPut( x, n / 2 );
    p = (long long)p * p % l;
    if ( n % 2 == 1 )
        p = (long long)p * x % l;

    return p;
}

int invmod( int x ) {
    return lgPut( x, l - 2 );
}

void calcSizes( int u, int p ) {
    sz[u] = 1;
    for ( int v: edges[u] ) {
        if ( v == p || vis[v] )
            continue;
        calcSizes( v, u );
        sz[u] += sz[v];
    }
}

int cen, totSz;
void findCentroid( int u, int p ) {
    int maxSize = 0;
    for ( int v: edges[u] ) {
        if ( v == p || vis[v] )
            continue;
        findCentroid( v, u );
        maxSize = max( maxSize, sz[v] );
    }
    maxSize = max( maxSize, totSz - sz[u] );

    if ( maxSize <= totSz / 2 )
        cen = u;
}

void dfs( int u, int p, int g ) {
    depth[u] = depth[p] + 1;
    for ( update upd: updatesV[u] ) {
        upd.g = g;
        updates.push_back( upd );
    }
    for ( query qry: queriesV[u] ) {
        qry.g = g;
        queries.push_back( qry );
    }
    for ( int v: edges[u] ) {
        if ( v == p || vis[v] )
            continue;
        dfs( v, u, g );
    }
}

void decomp( int r ) {
    calcSizes( r, 0 );
    totSz = sz[r];
    findCentroid( r, 0 );
    int c = cen;

    int g = 1;
    updates.clear();
    queries.clear();
    depth[c] = 0;
    for ( update upd: updatesV[c] ) {
        upd.g = g;
        updates.push_back( upd );
    }
    for ( query qry: queriesV[c] ) {
        qry.g = g;
        queries.push_back( qry );
    }
    for ( int v: edges[c] ) {
        if ( vis[v] )
            continue;
        ++g;
        dfs( v, c, g );
    }
    sort( updates.begin(), updates.end(), []( update x, update y ) {
        return x.t < y.t;
    } );
    sort( queries.begin(), queries.end(), []( query x, query y ) {
        return x.t < y.t;
    } );

    aibNI.init( g, n + 1 );
    aibII.init( g, n + 1 );

    int pu = 0;
    for ( query q: queries ) {
        while ( pu < updates.size() && updates[pu].t < q.t ) {
            if ( updates[pu].d >= depth[updates[pu].v] ) {
                aibNI.update( updates[pu].g, (n + 1) - min( n, (updates[pu].d - depth[updates[pu].v]) ), updates[pu].x );
                aibII.update( (g + 1) - updates[pu].g, (n + 1) - min( n, (updates[pu].d - depth[updates[pu].v]) ), updates[pu].x );
            }
            pu++;
        }
        if ( q.g == 1 )
            ans[q.t] = (long long)ans[q.t] * aibNI.query( g, (n + 1) - depth[q.v] ) % l;
        else
            ans[q.t] = (long long)ans[q.t] * aibNI.query( q.g - 1, (n + 1) - depth[q.v] ) % l * aibII.query( (g + 1) - (q.g + 1), (n + 1) - depth[q.v] ) % l;
    }

    vis[c] = true;
    for ( int v: edges[c] ) {
        if ( !vis[v] )
            decomp( v );
    }
}


int main() {
    cin >> n >> l;
    for ( int i = 0; i < n - 1; i++ ) {
        int u, v;
        cin >> u >> v;
        edges[u].push_back( v );
        edges[v].push_back( u );
    }
    for ( int v = 1; v <= n; v++ )
        cin >> h[v];
    int q;
    cin >> q;
    for ( int i = 0; i < q; i++ ) {
        int t;
        cin >> t;
        if ( t == 1 ) {
            int v, d, x;
            cin >> v >> d >> x;
            updatesV[v].push_back( { v, 0, d, x, i } );
            ans[i] = -1;
        } else {
            int v;
            cin >> v;
            queriesV[v].push_back( { v, 0, i } );
            ans[i] = h[v];
        }
    }

    decomp( 1 );

    for ( int i = 0; i < q; i++ ) {
        if ( ans[i] != -1 )
            cout << ans[i] << "\n";
    }

    return 0;
}

Compilation message (stderr)

sprinkler.cpp: In function 'void decomp(int)':
sprinkler.cpp:158:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<update>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  158 |         while ( pu < updates.size() && updates[pu].t < q.t ) {
      |                 ~~~^~~~~~~~~~~~~~~~
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...