Cod sursa(job #1413924)

Utilizator retrogradLucian Bicsi retrograd Data 2 aprilie 2015 10:58:08
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.84 kb
#include<fstream>
#include<vector>
#include<algorithm>

using namespace std;
typedef int var;

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

#define MAXN 300000
#define INF (1 << 30)
#define mid(a, b) ((a+b)>>1)

var HEAVY[MAXN], D[MAXN], VAL[MAXN];
var In[MAXN], PathP[MAXN], N[MAXN], Poz[MAXN];
var paths;
vector<var> Paths[MAXN];
vector<var> G[MAXN];
var n;

void dfs(var node) {
    HEAVY[node] = 1;
    var M = -1;
    var choose = -1;

    for(auto vec : G[node]) {

        if(!HEAVY[vec]) {
            D[vec] = D[node] + 1;
            dfs(vec);
            HEAVY[node] += HEAVY[vec];
            PathP[In[vec]] = node;

            if(M < HEAVY[vec]) {
                choose = In[vec];
                M = HEAVY[vec];
            }
        }

    }

    if( M == -1 ) {
        Paths[paths].push_back(node);
        In[node] = paths;
        paths ++;
    } else {
        Paths[choose].push_back(node);
        In[node] = choose;
    }
}

struct SegmentTree {
    var *TREE;
    var n;

    var qb, qe;
    var _poz, _val;

    SegmentTree(vector<var> &V, var n) {
        TREE = new var[4*n];
        this->n = n;
        build_tree(1, 1, n, V);
    }

    void build_tree(var node, var b, var e, vector<var> &V) {
        if(b == e) {
            TREE[node] = VAL[V[b]];
            return;
        }

        var m = mid(b, e);
        build_tree(node<<1, b, m, V);
        build_tree(node<<1|1, m+1, e, V);
        TREE[node] = max(TREE[node<<1], TREE[node<<1|1]);
    }

    void update(var node, var b, var e) {
        if(b == e) {
            TREE[node] = _val;
            return;
        }

        var m = mid(b, e);
        if(_poz <= m)
            update(node<<1, b, m);
        else
            update(node<<1|1, m+1, e);
        TREE[node] = max(TREE[node<<1], TREE[node<<1|1]);
    }

    void doUpdate(var poz, var val) {
        _poz = poz;
        _val = val;
        update(1, 1, n);
    }

    var query(var node, var b, var e) {
        if(b >= qb && e <= qe) {
            return TREE[node];
        }

        if(b > qe || e < qb) {
            return -INF;
        }

        var m = mid(b, e);
        return max(query(node<<1, b, m), query(node<<1|1, m+1, e));
    }

    var getQuery(var l, var r) {
        qb = l;
        qe = r;
        return query(1, 1, n);
    }

};
vector<SegmentTree> Trees;


int main() {

    var m, a, b, q, type;
    fin>>n>>q;

    for(var i=1; i<=n; i++) {
        fin>>VAL[i];
    }

    m = n-1;
    while(m--) {
        fin>>a>>b;
        G[a].push_back(b);
        G[b].push_back(a);
    }

    dfs(1);
    PathP[In[1]] = 0;

    for(var i=0; i<paths; i++) {
        Paths[i].push_back(0);
        reverse(Paths[i].begin(), Paths[i].end());
        N[i] = Paths[i].size() - 1;
        Trees.push_back(SegmentTree(Paths[i], N[i]));

        for(var j=1; j<=N[i]; j++) {
            Poz[Paths[i][j]] = j;
        }
    }

    while(q--) {
        fin>>type>>a>>b;

        if(type == 0) {
            VAL[a] = b;
            Trees[In[a]].doUpdate(Poz[a], VAL[a]);
        } else {
            var p1 = In[a],
                p2 = In[b];

            var rez = -INF;
            while(p1 != p2) {
                if(D[PathP[p1]] > D[PathP[p2]]){
                    rez = max(rez, Trees[p1].getQuery(1, Poz[a]));
                    a = PathP[p1];
                    p1 = In[a];
                } else {
                    rez = max(rez, Trees[p2].getQuery(1, Poz[b]));
                    b = PathP[p2];
                    p2 = In[b];
                }
            }

            if(Poz[a] > Poz[b])
                swap(a, b);

            rez = max(rez, Trees[p1].getQuery(Poz[a], Poz[b]));

            fout<<rez<<'\n';
        }

    }

    return 0;
}