Cod sursa(job #3259789)

Utilizator andrei_marciucMarciuc Andrei andrei_marciuc Data 27 noiembrie 2024 20:18:57
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.78 kb
#include <bits/stdc++.h>

using namespace std;

#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize ("unroll-loops")
    
static inline int min( int a, int b ) {
    return ( a <= b ? a : b );
}
 
static inline int max( int a, int b ) {
    return ( a >= b ? a : b );
}
 
static inline int mod( int x ) {
    return x < 0 ? -x : x;
}
    
FILE *fin;
 
int poz, valBuff;
static char buff[ ( 1 << 10 ) ];
static inline char nextChar() {
    if( poz == valBuff ) {
        fread( buff, 1, valBuff, fin );
        poz = 0;
    }
 
    return buff[ poz++ ];
}
 
static bool f[ 100 ];
static inline int readInt() {
    int rez = 0;
    int ch;
 
    while( !f[ ch = nextChar() ] );
    do
        rez = rez * 10 + ch - '0';
    while( f[ ch = nextChar() ] );
 
    return rez;
}
 
/////////////////////////////////////////////////////////////////////////////////////////////

const int MAXN = 1e5 + 1;

struct SegmentTree {
    int root, left, right;
    int SegmentTree[ 2 * MAXN ];

    void init( int minVal, int maxVal ) {
        root = 1;
        left = minVal;
        right = maxVal;
    }

    void update( int nod, int l, int r, int p, const int& x ) {
        if ( l == r ) {
            SegmentTree[ nod ] = x;
            return;
        }

        int med = ( l + r ) >> 1;
        int R = nod + 2 * ( med - l + 1 );
        int L = nod + 1;

        if( p <= med )
            update( L, l, med, p, x );
        else update( R, med + 1, r, p, x );
        SegmentTree[ nod ] = max( SegmentTree[ L ], SegmentTree[ R ] );
    }

    void update( int p, const int& x ) {
        update( root, left, right, p, x );
    }

    int query( int nod, int l, int r, int lq, int rq ) {
        if( r < lq || l > rq )
            return 0;
        if( lq <= l && r <= rq )
            return SegmentTree[ nod ];

        int med = ( l + r ) >> 1;
        int R = nod + 2 * ( med - l + 1 );
        int L = nod + 1;

        return max( query( L, l, med, lq, rq ), query( R, med + 1, r, lq, rq ) );
    }

    int query( int l, int r ) {
        return query( root, left, right, min( l, r ), max( l, r ) );
    }
};


struct HEAVY {
    int time;
    SegmentTree maxx;

    vector<int>adj[MAXN];
    vector<int> poz, heavy;
    vector<int> depth, parent, head;

    void add(const int& x, const int& y) {
        adj[x].emplace_back(y);
        adj[y].emplace_back(x);
    }

    void init(int size) {
        time = 0;
        size += 2;
        poz.resize(size);
        head.resize(size);
        depth.resize(size);
        heavy.resize(size);
        parent.resize(size);
        maxx.init(0, size - 1);


        dfs();
        decompose();
    }

    int dfs(int nod = 0, int dad = -1) {
        int sizeNod = 1;
        int sizeNxt = 0;
        int maxSize = 0;

        heavy[nod] = -1;
        parent[nod] = dad;
        for(const auto nxt : adj[nod])
            if(nxt != dad) {
                depth[nxt] = depth[nod] + 1;
                sizeNxt = dfs(nxt, nod);
                sizeNod += sizeNxt;
                if(sizeNxt > maxSize) {
                    maxSize = sizeNxt;
                    heavy[nod] = nxt;
                }
            }

        return sizeNod;
    }

    void decompose(int nod = 0, int dad = -1, int cap = 0) {
        head[nod] = cap;
        poz[nod] = time++;
        if(heavy[nod] != -1)
            decompose(heavy[nod], nod, cap);
        for(const auto &nxt : adj[nod])
            if(nxt != dad && nxt != heavy[nod])
                decompose(nxt, nod, nxt);
    } 

    void update(int nod, const int& val) {
        maxx.update(poz[nod], val);
    }

    int query(int a, int b) {
        int rez = 0;
        while(head[a] != head[b]) {
            if(depth[head[a]] > depth[head[b]])
                swap(a, b);
            rez = max(rez, maxx.query(poz[head[b]], poz[b]));
            b = parent[head[b]];
        }
        if(depth[a] > depth[b])
            swap(a, b);
        rez = max(rez, maxx.query(poz[a], poz[b]));
        return rez;
    }   
};

int v[MAXN];
HEAVY heavy;
int n, m;

int main()
{
    f[ '0' ] = f[ '1' ] = f[ '2' ] = f[ '3' ] = f[ '4' ] = 1;
    f[ '5' ] = f[ '6' ] = f[ '7' ] = f[ '8' ] = f[ '9' ] = 1;
    valBuff = sizeof( buff );
 
    fin = fopen( "heavypath.in", "r" );
    fread( buff, 1, valBuff, fin );
    
    n = readInt();
    m = readInt();
    for(int i = 0; i < n; i++)
        v[i] = readInt();

    int x, y;
    for(int i = 1; i < n; i++)
        heavy.add(readInt() - 1, readInt() - 1);

    heavy.init( n );
    for( int u = 0; u < n; u++ )
        heavy.update( u, v[ u ] );

    freopen("heavypath.out", "w", stdout);

    bool type;
    int a, b;
    while(m--) {
        type = readInt();
        a = readInt();
        b = readInt();

        if(type)
            cout << heavy.query(a - 1, b - 1) << '\n';
        else heavy.update(a - 1, b);
    }
    return 0;
}