Cod sursa(job #1956048)

Utilizator eu3neuomManghiuc Teodor-Florin eu3neuom Data 6 aprilie 2017 14:14:08
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.93 kb
#include <bits/stdc++.h>

using namespace std;

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

const int NMax = 1e5 + 5;

vector < int > G[NMax], Paths[NMax];
int value[NMax], w[NMax], level[NMax];
int l[NMax], lDim[NMax], lFather[NMax], lLevel[NMax], lPos[NMax];
int aint[4 * NMax];
bool viz[NMax];

int pathNumber = 0;
void DFS(const int &node) {
    viz[node] = true;
    w[node] = 1;

    int bestNext = -1;
    bool leaf = true;
    for(auto const &it: G[node]) {
        if(viz[it] == false) {
            level[it] = level[node] + 1;
            DFS(it);

            leaf = false;
            if(bestNext == -1) {
                bestNext = it;
            } else {
                if(w[it] > w[bestNext]) {
                    bestNext = it;
                }
            }
            w[node] += w[it];
        }
    }

    if(leaf == true) {
        l[node] = ++pathNumber;
        lDim[pathNumber] = 1;
        Paths[pathNumber].push_back(node);
        return;
    }

    l[node] = l[bestNext];
    lDim[l[node]]++;
    Paths[l[node]].push_back(node);

    for(auto const &it: G[node]) {
        if(it == bestNext || level[it] < level[node]) continue;
        lFather[l[it]] = node;
        lLevel[l[it]] = level[node];
    }
}

void buildAINT(const int &node, const int &lo, const int &hi, const int &lError, const int &lant) {
    if(lo == hi) {
        aint[node + lError] = value[Paths[lant][lo - 1]];
        return;
    }

    int mid = (lo + hi) >> 1;
    buildAINT(node * 2, lo, mid, lError, lant);
    buildAINT(node * 2 + 1, mid + 1, hi, lError, lant);

    aint[node + lError] = max(aint[node * 2 + lError], aint[node * 2 + 1 + lError]);
}

inline void makePaths() {
    level[1] = 1;
    DFS(1);

    for(int i = 1; i <= pathNumber; i++) {
        reverse(Paths[i].begin(), Paths[i].end());

        if(i > 1) lPos[i] = lPos[i - 1] + 4 * lDim[i - 1];
        buildAINT(1, 1, lDim[i], lPos[i], i);
    }
}

void Update(const int &node, const int &lo, const int &hi, const int &pos, const int &value, const int &lError) {
    if(lo == hi) {
        aint[node + lError] = value;
        return;
    }

    int mid = (lo + hi) >> 1;
    if(pos <= mid) {
        Update(node * 2, lo, mid, pos, value, lError);
    } else {
        Update(node * 2 + 1, mid + 1, hi, pos, value, lError);
    }

    aint[node + lError] = max(aint[2 * node + lError], aint[2 * node + 1 + lError]);
}

int Query(const int &node, const int &lo, const int &hi, const int &a, const int &b, const int &lError) {
    if(lo >= a && b >= hi) {
        return aint[node + lError];
    }

    int mid = (lo + hi) >> 1;
    int A, B;
    A = B = 0;
    if(a <= mid) A = Query(node * 2, lo, mid, a, b, lError);
    if(mid < b) B = Query(node * 2 + 1, mid + 1, hi, a, b, lError);

    return max(A, B);
}

int main() {
    ios::sync_with_stdio(false);

    int n, t;
    fin >> n >> t;

    for(int i = 1; i <= n; i++) fin >> value[i];
    for(int i = 1; i < n; i++) {
        int x, y;
        fin >> x >> y;

        G[x].push_back(y);
        G[y].push_back(x);
    }

    makePaths();
    while(t--) {
        int type, x, y;
        fin >> type >> x >> y;

        if(type == 0) {
            Update(1, 1, lDim[l[x]], level[x] - lLevel[l[x]], y, lPos[l[x]]);
        } else {
            int sol = 0;
            while(true) {
                if(l[x] == l[y]) {
                    if(level[x] > level[y]) swap(x, y);
                    sol = max(sol, Query(1, 1, lDim[l[x]], level[x] - lLevel[l[x]], level[y] - lLevel[l[x]], lPos[l[x]]));
                    break;
                }

                if(lLevel[l[x]] < lLevel[l[y]]) swap(x, y);
                sol = max(sol, Query(1, 1, lDim[l[x]], 1, level[x] - lLevel[l[x]], lPos[l[x]]));

                x = lFather[l[x]];
            }

            fout << sol << "\n";
        }
    }
    return 0;
}