Cod sursa(job #1411909)

Utilizator mirceadinoMircea Popoveniuc mirceadino Data 1 aprilie 2015 00:16:30
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.63 kb
#include<algorithm>
#include<bitset>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<fstream>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<vector>

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 A[NMAX];
vector<int> V[NMAX];
vector<int> lant[NMAX];
int path[NMAX];
int dad[NMAX];
int lvl[NMAX];
int weigth[NMAX];
int poz[NMAX];
int len[NMAX];
bitset<NMAX> viz;
vector<int> AI[NMAX];

void dfs(int x) {
    weigth[x] = 1;
    viz[x] = 1;
    lvl[x] = lvl[dad[x]] + 1;

    for(auto y : V[x])
        if(!viz[y]) {
            dad[y] = x;
            dfs(y);
            weigth[x] += weigth[y];
        }

    if(weigth[x] == 1) {
        P++;
        lant[P].push_back(x);
        path[x] = P;
    } else {
        int son  = 0;

        for(auto y : V[x])
            if(y != dad[x] && weigth[y] > weigth[son])
                son = y;

        lant[path[son]].push_back(x);
        path[x] = path[son];
    }
}

void build(int p, int nod, int lo, int hi) {
    if(lo == hi) {
        AI[p][nod] = A[lant[p][lo]];
        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 update(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)
        update(p, 2 * nod + 0, lo, mi + 0, poz, val);
    else
        update(p, 2 * nod + 1, mi + 1, hi, poz, val);

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

void updateaza(int x, int val) {
    update(path[x], 1, 1, len[path[x]], poz[x], val);
}

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

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

    int mi = (lo + hi) / 2;

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

    return max(q1, q2);
}

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

    while(path[x] != path[y]) {
        if(lvl[dad[lant[path[x]][1]]] > lvl[dad[lant[path[y]][1]]])
            swap(x, y);

        ans = max(ans, query(path[y], 1, 1, len[path[y]], 1, poz[y]));
        y = dad[lant[path[y]][1]];
    }

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

    ans = max(ans, query(path[x], 1, 1, len[path[x]], poz[x], poz[y]));

    return ans;
}

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

#ifndef ONLINE_JUDGE
    freopen(inputFile.c_str(), "r", stdin);
    freopen(outputFile.c_str(), "w", stdout);
#endif

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

    for(i = 1; i <= N; i++)
        scanf("%d", &A[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);

    for(p = 1; p <= P; p++) {
        lant[p].push_back(0);
        reverse(lant[p].begin(), lant[p].end());
        len[p] = lant[p].size() - 1;

        for(i = 1; i <= len[p]; i++)
            poz[lant[p][i]] = i;

        AI[p].resize(4 * len[p] + 5);

        build(p, 1, 1, len[p]);
    }

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

        if(!t)
            updateaza(x, y);
        else
            printf("%d\n", queryaza(x, y));
    }

    return 0;
}