Cod sursa(job #1413956)

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

using namespace std;
typedef int var;

#define MAXN 100005
#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;
    }
}

class SegmentTree {
    var *TREE;
    var n;
    var ind;

    var qb, qe;
    var _poz;
    var _r;

    public:

    SegmentTree(var ind) {
        this->ind = ind;
        this->n = N[ind];
        TREE = new var[4*n];
        build_tree(1, 1, n);
    }

    void build_tree(var node, var b, var e) {
        if(b == e) {
            TREE[node] = VAL[Paths[ind][b]];
            return;
        }

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

    void update(var node, var b, var e) {
        if(b == e) {
            TREE[node] = VAL[Paths[ind][b]];
            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) {
        _poz = poz;
        update(1, 1, n);
    }

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

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

        var m = mid(b, e);
        if(qb <= m)
            query(node<<1, b, m);
        if(qe > m)
            query(node<<1|1, m+1, e);
    }

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

};
vector<SegmentTree> Trees;


int main() {

    freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);

    var m, a, b, q, type;
    scanf("%d%d", &n, &q);

    for(var i=1; i<=n; i++) {
        scanf("%d", &VAL[i]);
    }

    m = n-1;
    while(m--) {
        scanf("%d%d", &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(i));

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

    while(q--) {
        scanf("%d%d%d", &type, &a, &b);

        if(type == 0) {
            VAL[a] = b;
            Trees[In[a]].doUpdate(Poz[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]));

            printf("%d\n", rez);
        }

    }

    return 0;
}