Cod sursa(job #1365735)

Utilizator mirceadinoMircea Popoveniuc mirceadino Data 28 februarie 2015 14:45:56
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.71 kb
#include<cstdio>
#include<string>
#include<vector>
#include<algorithm>

using namespace std;

#ifdef HOME
const string inputFile = "input.txt";
const string outputFile = "output.txt";
#else
const string problemName = "heavypath";
const string inputFile = problemName + ".in";
const string outputFile = problemName + ".out";
#endif

const int NMAX = 100000 + 5;

int N, M, P;
int val[NMAX];
vector<int> V[NMAX];
vector<int> path[NMAX];
int dad[NMAX];
int lvl[NMAX];
int son[NMAX];
int weigth[NMAX];
int which_path[NMAX];
int lvl_path[NMAX];
int poz[NMAX];
vector<int> AI[NMAX];

void dfs(int x) {
    son[x] = 0;
    weigth[x] = 1;

    for(auto y : V[x])
        if(y != dad[x]) {
            dad[y] = x;
            lvl[y] = lvl[x] + 1;

            dfs(y);

            weigth[x] += weigth[y];
            if(weigth[y] > weigth[son[x]])
                son[x] = y;
        }
}

void get_paths(int x) {
    if(weigth[x] == 1) {
        path[++P].push_back(x);
        which_path[x] = P;
        lvl_path[P] = lvl[x];
        return;
    }

    for(auto y : V[x])
        if(y != dad[x])
            get_paths(y);

    path[which_path[son[x]]].push_back(x);
    which_path[x] = which_path[son[x]];
    lvl_path[which_path[x]] = lvl[x];
}

void build(int P, int nod, int lo, int hi) {
    if(lo == hi) {
        AI[P][nod] = val[path[P][lo - 1]];
        return;
    }

    int mi = (lo + hi) / 2;

    build(P, 2 * nod + 0, lo, mi + 0);
    build(P, 2 * nod + 1, mi + 1, hi);

    AI[P][nod] = max(AI[P][2 * nod + 0], AI[P][2 * nod + 1]);
}

void upd(int P, int nod, int lo, int hi, int poz, int val) {
    if(lo == hi) {
        AI[P][nod] = val;
        return;
    }

    int mi = (lo + hi) / 2;

    if(poz <= mi) upd(P, 2 * nod + 0, lo, mi + 0, poz, val);
    else upd(P, 2 * nod + 1, mi + 1, hi, poz, val);

    AI[P][nod] = max(AI[P][2 * nod + 0], AI[P][2 * nod + 1]);
}

int qry(int P, int nod, int lo, int hi, int L, int R) {
    if(L <= lo && hi <= R)
        return AI[P][nod];

    if(R < lo || hi < L)
        return -1;

    int mi = (lo + hi) / 2;

    int q1 = qry(P, 2 * nod + 0, lo, mi + 0, L, R);
    int q2 = qry(P, 2 * nod + 1, mi + 1, hi, L, R);

    return max(q1, q2);
}

void update(int x, int v) {
    val[x] = v;
    upd(which_path[x], 1, 1, path[which_path[x]].size(), poz[x], v);
}

int query(int x, int y) {
    int ans = -1;

    while(which_path[x] != which_path[y]) {
        if(lvl_path[which_path[x]] < lvl_path[which_path[y]]) {
            ans = max(ans, qry(which_path[y], 1, 1, path[which_path[y]].size(), 1, poz[y]));
            y = dad[path[which_path[y]][0]];
        } else {
            ans = max(ans, qry(which_path[x], 1, 1, path[which_path[x]].size(), 1, poz[x]));
            x = dad[path[which_path[x]][0]];
        }
    }

    if(poz[x] > poz[y])
        swap(x, y);

    ans = max(ans, qry(which_path[x], 1, 1, path[which_path[x]].size(), poz[x], poz[y]));

    return ans;
}

int main() {
    int i, j, t, x, y;

    freopen(inputFile.c_str(), "r", stdin);
    freopen(outputFile.c_str(), "w", stdout);

    scanf("%d%d", &N, &M);

    for(i = 1; i <= N; i++)
        scanf("%d", &val[i]);

    for(i = 1; i <= N - 1; i++) {
        scanf("%d%d", &x, &y);
        V[x].push_back(y);
        V[y].push_back(x);
    }

    dfs(1);
    get_paths(1);

    for(i = 1; i <= P; i++) {
        reverse(path[i].begin(), path[i].end());

        for(j = 0; j < path[i].size(); j++)
            poz[path[i][j]] = j + 1;

        AI[i].resize(4 * path[i].size() + 10);

        build(i, 1, 1, path[i].size());
    }

    while(M--) {
        scanf("%d%d%d", &t, &x, &y);

        if(!t) {
            update(x, y);
            continue;
        }

        if(t) {
            printf("%d\n", query(x, y));
            continue;
        }
    }

    return 0;
}