Cod sursa(job #2191258)

Utilizator felixiPuscasu Felix felixi Data 2 aprilie 2018 12:24:32
Problema Heavy Path Decomposition Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 4.08 kb
#include <bits/stdc++.h>

using namespace std;

const int NMAX = 1e5;

int val[NMAX+2];

namespace HLD
{
    /// one time use only, reset by hand if necessary
    const int NMAX = ::NMAX;
    const int INF  = (1 << 30);

    struct Atom
    {
        int cnt, val;

        Atom(int cnt = 0, int val = -INF) : cnt(cnt), val(val) {}
    };

    Atom combine(const Atom& a, const Atom& b)
    {
        return Atom(a.cnt + b.cnt, max(a.val, b.val));
    }

    int root[NMAX+2], treePos[NMAX+2], unde[NMAX+2];
    int parent[NMAX+2], heavy[NMAX+2], depth[NMAX+2];
    vector<Atom> aint[NMAX+2];
    int _nr, _lg[NMAX+2];

    void upd_aint(int care, int nod, int st, int dr, int poz, int val)
    {
        if( poz < st || poz > dr ) return ;

        if( st == dr ) {
            aint[care][nod] = Atom(1, val);
            return ;
        }

        int m = (st + dr) / 2;
        upd_aint(care, 2*nod, st, m, poz, val);
        upd_aint(care, 2*nod + 1, m+1, dr, poz, val);

        aint[care][nod] = combine(aint[care][2*nod], aint[care][2*nod + 1]);
    }

    int qry_aint(int care, int nod, int st, int dr, int x, int y)
    {
        if( y < st || dr < x ) return -INF;
        if( x <= st && dr <= y ) {
            ///cerr << "qry: " << care << ": " << st << '-' << dr << ": " << aint[care][nod].val << '\n';
            return aint[care][nod].val;
        }

        int m = (st + dr) / 2;
        int a = qry_aint(care, 2*nod, st, m, x, y);
        int b = qry_aint(care, 2*nod + 1, m+1, dr, x, y);


        return max(a, b);
    }

    int query(int x, int y)
    {
        int ret = -INF;
        while( root[x] != root[y] ) {
            if( depth[x] < depth[y] ) swap(x, y);
            ret = max(ret, qry_aint(unde[x], 1, 1,_lg[ unde[x] ], 1, treePos[x]));
            x = parent[ root[x] ];
        }

        if( depth[x] > depth[y] ) swap(x, y);
        ret = max(ret, qry_aint(unde[x], 1, 1,_lg[ unde[x] ], treePos[x], treePos[y]));

        return ret;
    }

    void update(int nod, int val)
    {
        ///cerr << "aint: " << unde[nod] << ", lg: " << _lg[ unde[nod] ] << ", poz: " << treePos[nod] << ", val: " << val << '\n';
        upd_aint(unde[nod], 1, 1,_lg[ unde[nod] ], treePos[nod], val);
    }

    int dfs(const vector<int>(& G)[NMAX+2], int nod, int father = -1)
    {
        if( father == -1 ) depth[nod] = 1;
        int cat = 1;

        int greu = 0;
        for( int x : G[nod] ) {
            if( x == father ) continue;
            parent[x] = nod;
            depth[x] = depth[nod] + 1;

            int subTree = dfs(G, x, nod);
            if( subTree > greu )
                heavy[nod] = x, greu = subTree;

            cat += subTree;
        }
        return cat;
    }

    void init(const vector<int>(& G)[NMAX+2], int noduri)
    {
        parent[0] = -1;
        parent[1] = 0;
        dfs(G, 1);
        for( int i = 1;  i <= noduri;  ++i ) {
            if( parent[i] == 0 || heavy[ parent[i] ] != i ) {
                ++_nr;
                for( int x = i, cnt = 1;  1 <= x && x <= noduri;  x = heavy[x], ++cnt )
                    treePos[x] = cnt, _lg[_nr] = cnt, root[x] = i, unde[x] = _nr;
                aint[_nr] = vector<Atom>(4 * _lg[_nr] + 2);
                for( int x = i, cnt = 1;  1 <= x && x <= noduri;  x = heavy[x], ++cnt )
                    update(x, ::val[x]);
            }
        }
    }
}

ifstream in("heavypath.in");
ofstream out("heavypath.out");

vector<int> G[NMAX+2];
int N, Q;

int main()
{
    in >> N >> Q;
    for( int i = 1;  i <= N;  ++i ) in >> val[i];
    for( int i = 1;  i < N;  ++i ) {
        int x,y;
        in >> x >> y;
        G[x].push_back(y);
        G[y].push_back(x);
    }
    HLD::dfs(G, 1);
    HLD::init(G, N);
    for( int i = 1;  i <= N;  ++i )
        HLD::update(i, val[i]);

    for( int i = 1;  i <= Q;  ++i ) {
        int t,x,y;
        in >> t >> x >> y;
        if( t == 0 ) {
            HLD::update(x, y);
        }
        else
            out << HLD::query(x, y) << '\n';
    }
    return 0;
}