Cod sursa(job #2092526)

Utilizator Alex18maiAlex Enache Alex18mai Data 21 decembrie 2017 21:15:09
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.48 kb
#include <fstream>
#include <vector>

using namespace std;

ifstream cin("heavypath.in");
ofstream cout("heavypath.out");

int val[100100];

vector<vector<int> > gr(100100);
vector<bool> used(100100);

vector<vector<int> > arb(100100);
vector<vector<int> > Arb(100100);
vector<int> G (100100);
vector<int> tata_lant(100100);
vector<int> lant(100100);
vector<int> lv(100100);
vector<int> pos(100100);
int cont = 0;

void dfs(int root) {

    G[root] = 1;
    used[root] = true;
    int MAX = 0;
    int go = 0;
    int last = 0;

    for (auto &x : gr[root]) {
        if (used[x]) {
            last = x;
            continue;
        }
        lv[x] = lv[root] + 1;
        dfs(x);
        G[root] += G[x];
        if (MAX < G[x]) {
            MAX = G[x];
            go = x;
        }

    }

    if (go == 0) {
        cont++;
        arb[cont].push_back(root);
        lant[root] = cont;
        pos[root] = 1;
    } else {
        arb[lant[go]].push_back(root);
        lant[root] = lant[go];
        pos[root] = arb[lant[root]].size();
        for (auto &x : gr[root]) {
            if (x == last || x == go) {
                continue;
            }
            tata_lant[lant[x]] = root;
        }
    }

}

void Resize() {

    for (int i = 1; i <= cont; i++) {
        Arb[i].resize(arb[i].size() * 4);
    }

}

void Update(int nod, int st, int dr, int poz, int val, int ARB) {

    if (st == dr) {
        Arb[ARB][nod] = val;
        return;
    }

    int mij = st + dr;
    mij /= 2;

    if (mij >= poz) {
        Update(nod * 2, st, mij, poz, val, ARB);
    } else {
        Update(nod * 2 + 1, mij + 1, dr, poz, val, ARB);
    }

    Arb[ARB][nod] = max(Arb[ARB][nod * 2], Arb[ARB][nod * 2 + 1]);

}

void Querry(int nod, int st, int dr, int MIN, int MAX, int ARB, int &maxx) {

    if (MIN <= st && MAX >= dr) {
        maxx = max(maxx, Arb[ARB][nod]);
        return;
    }

    int mij = st + dr;
    mij /= 2;

    if (mij >= MIN) {
        Querry(nod * 2, st, mij, MIN, MAX, ARB, maxx);
    }
    if (mij < MAX) {
        Querry(nod * 2 + 1, mij + 1, dr, MIN, MAX, ARB, maxx);
    }

}

int main() {

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    int n, m;
    cin >> n >> m;

    for (int i = 1; i <= n; i++) {
        cin >> val[i];
    }

    for (int i = 1; i < n; i++) {
        int a, b;
        cin >> a >> b;
        gr[a].push_back(b);
        gr[b].push_back(a);
    }

    dfs(1);

    Resize();

    for (int i = 1; i <= n; i++) {
        Update(1, 1, arb[lant[i]].size(), pos[i], val[i], lant[i]);
    }


    for (int i = 1; i <= m; i++) {
        int test, x, y;
        cin >> test >> x >> y;

        if (test == 0) {
            val[x] = y;
            Update(1, 1, arb[lant[x]].size(), pos[x], val[x], lant[x]);
        } else {
            int maxx = 0;
            while (lant[x] != lant[y]) {

                int lv_x = lv[arb[lant[x]][arb[lant[x]].size() - 1]];
                int lv_y = lv[arb[lant[y]][arb[lant[y]].size() - 1]];

                if (lv_x > lv_y) {
                    Querry(1, 1, arb[lant[x]].size(), pos[x], arb[lant[x]].size(), lant[x], maxx);
                    x = tata_lant[lant[x]];
                } else {
                    Querry(1, 1, arb[lant[y]].size(), pos[y], arb[lant[y]].size(), lant[y], maxx);
                    y = tata_lant[lant[y]];
                }

            }
            Querry(1, 1, arb[lant[x]].size(), min(pos[x], pos[y]), max(pos[x], pos[y]), lant[x], maxx);

            cout << maxx << '\n';

        }

    }

    return 0;
}