Cod sursa(job #1383284)

Utilizator retrogradLucian Bicsi retrograd Data 10 martie 2015 07:20:27
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.38 kb
#include<fstream>
#include<vector>
#include<deque>
#include<algorithm>

using namespace std;
typedef int var;

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

#define MAXN 100001

vector<var> G[MAXN];
vector<var> Path[MAXN];
var *Trees[MAXN];
var PathP[MAXN], Heavy[MAXN], Depth[MAXN], WhatPath[MAXN], WhatPos[MAXN], V[MAXN], N[MAXN];
var paths;

void dfs(var node, var depth) {
    Depth[node] = depth;
    Heavy[node] = 1;
    var M = -1, N;
    for(auto vec : G[node]) {
        if(Depth[vec] == 0) {
            dfs(vec, depth+1);
            Heavy[node] += Heavy[vec];
            PathP[WhatPath[vec]] = node;
            if(M < Heavy[vec]) {
                M = Heavy[vec];
                N = WhatPath[vec];
            }
        }
    }
    if(M == -1) {
        WhatPath[node] = ++paths;
    } else {
        WhatPath[node] = N;
    }
    Path[WhatPath[node]].push_back(node);
}

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(e<l || b>r) {
        return -1;
    }
    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 solve_for(var a, var b) {
    var rez = -1;
    var p1 = WhatPath[a], p2 = WhatPath[b];
    while(p1 != p2) {
        if(Depth[PathP[p1]] > Depth[PathP[p2]]) {
            rez = max(rez, query(p1, 1, 1, N[p1], 1, WhatPos[a]));
            a = PathP[p1];
            p1 = WhatPath[a];
        } else {
            rez = max(rez, query(p2, 1, 1, N[p2], 1, WhatPos[b]));
            b = PathP[p2];
            p2 = WhatPath[b];
        }
    }

    if(Depth[a] > Depth[b])
        swap(a, b);
    rez = max(rez, query(p1, 1, 1, N[p1], WhatPos[a], WhatPos[b]));
    return rez;
}

int main() {
    var n, m, a, b;
    fin>>n>>m;
    for(var i=1; i<=n; i++) {
        fin>>V[i];
    }
    for(var i=2; i<=n; i++) {
        fin>>a>>b;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    dfs(1, 1);
    //Some more preprocessing
    PathP[WhatPath[1]] = 0;
    for(var i=1; i<=paths; i++) {
        Path[i].push_back(0);
        N[i] = Path[i].size() - 1;
        reverse(Path[i].begin(), Path[i].end());
        for(var j=1; j<=N[i]; j++) {
            WhatPos[Path[i][j]] = j;
        }
        Trees[i] = new var[4*N[i]];
        build_tree(i, 1, 1, N[i]);
    }

    var type;
    while(m--) {
        fin>>type>>a>>b;
        if(type == 0) {
            update(WhatPath[a], 1, 1, N[WhatPath[a]], WhatPos[a], b);
        } else {
            fout<<solve_for(a, b)<<'\n';
        }
    }
}