Cod sursa(job #1367288)

Utilizator CosminRusuCosmin Rusu CosminRusu Data 1 martie 2015 19:15:09
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.42 kb
#include <iostream>
#include <vector>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

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

const int maxn = 100005;
const int oo = 0x3f3f3f3f;

int n, m, v[maxn], w[maxn], pathwhere[maxn], pathfather[maxn], paths, pathpos[maxn], level[maxn];
vector <int> g[maxn], path[maxn], arb[maxn];

inline void dfs(int node, int father) {
    w[node] = 1;
    level[node] = level[father] + 1;
    int heaviest = -1;
    for(auto it : g[node]) {
        if(it == father)
            continue;
        dfs(it, node);
        w[node] += w[it];
        if(heaviest == -1 || w[heaviest] < w[it])
            heaviest = it;
    }
    if(heaviest == -1) {
        pathwhere[node] = ++ paths;
        pathfather[pathwhere[node]] = father;
        path[pathwhere[node]].push_back(node);
        return ;
    }
    pathwhere[node] = pathwhere[heaviest];
    pathfather[pathwhere[node]] = father;
    path[pathwhere[node]].push_back(node);
}

inline void build(int node, int st, int dr, int ind) {
    if(st == dr) {
        arb[ind][node] = v[path[ind][st]];
        return ;
    }
    int mid = ((st + dr) >> 1);
    build(node << 1, st, mid, ind);
    build((node << 1) | 1, mid + 1, dr, ind);
    arb[ind][node] = max(arb[ind][node << 1], arb[ind][(node << 1) | 1]);
}

inline void update(int node, int st, int dr, int pos, int ind) {
    if(st == dr) {
        arb[ind][node] = v[path[ind][st]];
        return ;
    }
    int mid = ((st + dr) >> 1);
    if(pos <= mid)
        update(node << 1, st, mid, pos, ind);
    else
        update((node << 1) | 1, mid + 1, dr, pos, ind);
    arb[ind][node] = max(arb[ind][node << 1], arb[ind][(node << 1) | 1]);
}

inline int query(int node, int st, int dr, int a, int b, int ind) {
    if(a <= st && dr <= b)
        return arb[ind][node];
    int mid = ((st + dr) >> 1);
    int ret = -0x3f3f3f3f;
    if(a <= mid)
        ret = max(ret, query(node << 1, st, mid, a, b, ind));
    if(mid < b)
        ret = max(ret, query((node << 1) | 1, mid + 1, dr, a, b, ind));
    return ret;
}

inline int queryhp(int x, int y) {
    if(pathwhere[x] == pathwhere[y]) {
        if(pathpos[x] > pathpos[y])
            swap(x, y);
        return query(1, 0, path[pathwhere[x]].size() - 1, pathpos[x], pathpos[y], pathwhere[x]);
    }
    if(level[pathfather[pathwhere[x]]] < level[pathfather[pathwhere[y]]])
        swap(x, y);
    int act = query(1, 0, path[pathwhere[x]].size() - 1, 0, pathpos[x], pathwhere[x]);
    return max(act, queryhp(pathfather[pathwhere[x]], y));

}

int main() {
    fin >> n >> m;
    for(int i = 1 ; i <= n ; ++ i)
        fin >> v[i];
    for(int i = 1 ; i < n ; ++ i) {
        int x, y;
        fin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    dfs(1, 0);
    for(int i = 1 ; i <= paths ; ++ i) {
        reverse(path[i].begin(), path[i].end());
        for(int j = 0 ; j < path[i].size() ; ++ j)
            pathpos[path[i][j]] = j;
        arb[i].resize(path[i].size() << 2);
        build(1, 0, path[i].size() - 1, i);
    }
    for(int i = 1 ; i <= m ; ++ i) {
        int op, x, y;
        fin >> op >> x >> y;
        if(op == 0) {
            v[x] = y;
            update(1, 0, path[pathwhere[x]].size() - 1, pathpos[x], pathwhere[x]);
        }
        else
            fout << queryhp(x, y) << '\n';
    }
}