Cod sursa(job #1382964)

Utilizator retrogradLucian Bicsi retrograd Data 9 martie 2015 19:41:30
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 5.28 kb
#include<fstream>
#include<vector>
#include<deque>
#include<cmath>

using namespace std;

typedef int var;

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

#define MAXN 100001
#define INF (1<<28)
#define MAXD 1001

struct Rmq {
    var rmq, sol;
    const bool operator<(const Rmq &t) const {
        return rmq < t.rmq;
    }
    Rmq(var a, var b) {
        sol = a;
        rmq = b;
    }
    Rmq(){}
};


vector<var> G[MAXN];
deque<var> PATH[MAXD];
var PathP[MAXD];
var IN[MAXN], HEAVY[MAXN];
var V[MAXN], POZ[MAXN];
//var LOG[3*MAXN];
var N[MAXD];
var n, m, t;
var paths;
var *TREES[MAXD];
var BEG[MAXN];
//Rmq RMQ[17][3*MAXN];
Rmq EULER[3*MAXN], LCAT[9*MAXN];

void dfs(var node, var depth) {
    HEAVY[node] = 1;
    EULER[++t] = Rmq(node, depth);
    //RMQ[0][++t] = Rmq(node, depth);
    BEG[node] = t;
    var best = -1, in;
    for(auto vec : G[node]) {
        if(!BEG[vec]) {
            dfs(vec, depth+1);
            EULER[++t] = Rmq(node, depth);
            //RMQ[0][++t] = Rmq(node, depth);
            if(HEAVY[vec] > best) {
                best = HEAVY[vec];
                in = IN[vec];
            }
            PathP[IN[vec]] = node;
            HEAVY[node] += HEAVY[vec];
        }
    }
    if(best == -1) {
        IN[node] = ++paths;
        PATH[paths].push_front(node);
    } else {
        IN[node] = in;
        PATH[in].push_front(node);
    }
}
/*
void build_log() {
    for(var i=2; i<=3*n; i++) {
        LOG[i] = LOG[i/2] + 1;
    }
}

void build_rmq() {
    var n = t;
    for(var i=1; (1<<i) <= n; i++) {
        for(var j=1; j+(1<<i)-1<=n; j++) {
            RMQ[i][j] = min(RMQ[i-1][j], RMQ[i-1][j+(1<<(i-1))]);
        }
    }
}

var lca(var a, var b) {
    a = BEG[a];
    b = BEG[b];
    if(a > b) swap(a, b);
    var l = LOG[b-a+1];
    auto rez = min(RMQ[l][a], RMQ[l][b-(1<<l)+1]);
    return rez.sol;
}
*/


void build_lca_tree(var node, var b, var e) {
    if(b == e) {
        LCAT[node] = EULER[b];
    } else {
        var m = (b+e)/2;
        build_lca_tree(node*2, b, m);
        build_lca_tree(node*2+1, m+1, e);
        LCAT[node] = min(LCAT[node*2], LCAT[node*2+1]);
    }
}

Rmq queryL(var node, var b, var e, var l, var r) {
    if(b >= l && e <= r)
        return LCAT[node];
    if(l > e || r < b)
        return Rmq(INF, INF);
    var m = (b+e)/2;
    return min(queryL(node*2, b, m, l, r), queryL(node*2+1, m+1, e, l, r));
}

var lca(var n1, var n2) {
    n1 = BEG[n1];
    n2 = BEG[n2];
    if(n1 > n2) swap(n1, n2);
    Rmq res = queryL(1, 1, n, n1, n2);
    return res.sol;
}

void build_tree(var ind, var node, var b, var e) {
    var *TREE = TREES[ind];
    if(b == e) {
        TREE[node] = V[PATH[ind][b]];
    } else {
        var m = (b+e)/2;
        build_tree(ind, node*2, b, m);
        build_tree(ind, node*2+1, m+1, e);
        TREE[node] = max(TREE[node*2], TREE[node*2+1]);
    }
}

void update(var ind, var node, var b, var e, var poz, var val) {
    var *TREE = TREES[ind];
    if(b == e) {
        TREE[node] = val;
    } else {
        var m = (b+e)/2;
        if(poz <= m)
            update(ind, node*2, b, m, poz, val);
        else
            update(ind, node*2+1, m+1, e, poz, val);
        TREE[node] = max(TREE[node*2], TREE[node*2+1]);
    }
}

var query(var ind, var node, var b, var e, var l, var r) {
    var *TREE = TREES[ind];
    if(b >= l && e <= r)
        return TREE[node];
    if(l > e || r < b)
        return -INF;
    var m = (b+e)/2;
    return max(query(ind, node*2, b, m, l, r), query(ind, node*2+1, m+1, e, l, r));
}


var afla_max(var node, var parent) {
    var cur_path = IN[node];
    var end_index = POZ[node];
    var res = -INF;
    while(cur_path != IN[parent]) {
        res = max(res, query(cur_path, 1, 1, N[cur_path], 1, end_index));
        node = PathP[cur_path];
        end_index = POZ[node];
        cur_path = IN[node];
    }
    res = max(res, query(cur_path, 1, 1, N[cur_path], POZ[parent], POZ[node]));

    return res;
}

void afis(var ind, var node, var b, var e) {
    var *TREE = TREES[ind];
    fout<<"["<<b<<" " << e<<"] : "<<TREE[node]<<'\n';
    if(b == e) return;
    var m = (b+e)/2;
    afis(ind, node*2, b, m);
    afis(ind, node*2+1, m+1, e);
}





int main() {
    var a, b;
    fin>>n>>m;
    for(var i=1; i<=n; i++) {
        fin>>V[i];
    }
    var e = n-1;
    while(e--) {
        fin>>a>>b;
        G[a].push_back(b);
        G[b].push_back(a);
    }


    dfs(1, 0);
    //build_log();
    //build_rmq();
    build_lca_tree(1, 1, n);

    for(var i=1; i<=paths; i++) {
        PATH[i].push_front(0);
        for(var j=1; j<PATH[i].size(); j++) {
            POZ[PATH[i][j]] = j;
        }
    }

    for(var i=1; i<=paths; i++) {
        N[i] = PATH[i].size() - 1;
        var size = 1.0*log(N[i])/log(2);
        size ++;
        TREES[i] = new var[(1<<size) + 1];
        build_tree(i, 1, 1, N[i]);
    }

    var type, lc;


    while(m--) {
        fin>>type>>a>>b;
        if(type == 0) {
            update(IN[a], 1, 1, N[IN[a]], POZ[a], b);
        } else {
            var lc = lca(a, b);
            fout << max(afla_max(a, lc), afla_max(b, lc)) << '\n';
        }
    }

    return 0;
}