Cod sursa(job #2684970)

Utilizator giotoPopescu Ioan gioto Data 15 decembrie 2020 14:01:30
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.2 kb
#include <bits/stdc++.h>
using namespace std;

const int NMAX = 1e5 + 5;
const int INF = 2e9;

int n, m, nrLant;
int arb[4 * NMAX];
int pos[NMAX], tt[NMAX], sz[NMAX], heavy[NMAX], h[NMAX], val[NMAX], delta[NMAX], which[NMAX];
vector <int> v[NMAX], lant[NMAX];

void update(int delta, int pos, int val, int st, int dr, int nod = 1) {
    if (st == dr) {
        arb[nod + delta] = val;
        return ;
    }

    int mij = (st + dr) / 2;
    if (pos <= mij) update(delta, pos, val, st, mij, nod * 2);
    else update(delta, pos, val, mij + 1, dr, nod * 2 + 1);

    arb[nod + delta] = max(arb[nod * 2 + delta], arb[nod * 2 + 1 + delta]);
}

int query(int delta, int x, int y, int st, int dr, int nod = 1) {
    if (x <= st && dr <= y) return arb[nod + delta];

    int mij = (st + dr) / 2, ans = -INF;

    if (x <= mij) ans = max(ans, query(delta, x, y, st, mij, nod * 2));
    if (mij + 1 <= y) ans = max(ans, query(delta, x, y, mij + 1, dr, nod * 2 + 1));

    return ans;
}

void dfs(int nod) {
    sz[nod] = 1;
    heavy[nod] = 0;
    for (auto it : v[nod]) {
        if (it == tt[nod]) continue ;

        tt[it] = nod;
        h[it] = h[nod] + 1;
        dfs(it);
        sz[nod] += sz[it];

        if (heavy[nod] == 0 || sz[it] > sz[heavy[nod]]) heavy[nod] = it;
    }
}

void decompose(int nod, int whichLant) {
    lant[whichLant].push_back(nod);
    which[nod] = whichLant;
    pos[nod] = (int)lant[whichLant].size() - 1;
    if (heavy[nod] != 0) decompose(heavy[nod], whichLant);

    for (auto it : v[nod]) {
        if (it == tt[nod] || it == heavy[nod]) continue ;
        decompose(it, ++nrLant);
    }
}

void buildLant() {
    int sum = 0;
    for (int i = 1; i <= nrLant ; ++i) {
        delta[i] = sum;
        for (auto nod : lant[i])
            update(delta[i], pos[nod] + 1, val[nod], 1, (int)lant[i].size());
        sum += (int)lant[i].size() * 4;
    }
}

int getHeightLant(int nod) {
    return h[lant[which[nod]][0]];
}

int queryLant(int x, int y) {
    int ans = -INF;
    while (which[x] != which[y]) {
        if (getHeightLant(x) < getHeightLant(y)) swap(x, y);

        int ind = which[x];
        ans = max(ans, query(delta[ind], 1, pos[x] + 1, 1, (int)lant[ind].size()));
        x = tt[lant[ind][0]];
    }

    ///nodurile mele sunt pe acelasi lant
    ans = max(ans, query(delta[which[x]], min(pos[x], pos[y]) + 1, max(pos[x], pos[y]) + 1, 1, (int)lant[which[x]].size()));
    return ans;
}

int main() {
    freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);

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

    int x, y;
    for (int i = 1; i < n ; ++i) {
        scanf("%d%d", &x, &y);
        v[x].push_back(y);
        v[y].push_back(x);
    }

    dfs(1);
    decompose(1, ++nrLant);
    buildLant();

    int tip;
    while (m--) {
        scanf("%d%d%d", &tip, &x, &y);
        if (tip == 0) {
            val[x] = y;
            update(delta[which[x]], pos[x] + 1, val[x], 1, (int)lant[which[x]].size());
        } else if (tip == 1) printf("%d\n", queryLant(x, y));
    }

    return 0;
}