Cod sursa(job #2908623)

Utilizator StanCatalinStanCatalin StanCatalin Data 4 iunie 2022 19:01:20
Problema Heavy Path Decomposition Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.69 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

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

const int dim = 1e5 + 5;

int n, q, first[100], lst[100], nxt[dim], parent[dim], sz[dim], hp_id[dim], val[dim], rezultat, adancime[100], poz[dim];
vector<int> vec[dim];
vector<int> liste[dim];
vector<int> liste_arb[dim];

void Construieste_arbore(int nod, int st, int dr, int care) {
    if (st == dr) {
        liste_arb[care][nod] = val[liste[care][st-1]];
    } else {
        int mid = (st + dr) / 2;
        Construieste_arbore(2 * nod, st, mid, care);
        Construieste_arbore(2 * nod + 1, mid + 1, dr, care);
        liste_arb[care][nod] = max(liste_arb[care][2 * nod], liste_arb[care][2*nod+1]);
    }
}

void Update(int nod, int st, int dr, int care, int poz, int val) {
    if (st == dr) {
        liste_arb[care][nod] = val;
    } else {
        int mid = (st + dr) / 2;
        if (poz <= mid) {
            Update(2 * nod, st, mid, care, poz, val);
        } else {
            Update(2 * nod + 1, mid+1, dr, care, poz, val);
        }
        liste_arb[care][nod] = max(liste_arb[care][2 * nod], liste_arb[care][2*nod+1]);
    }
}

void Query(int nod, int st, int dr, int a, int b, int care) {
    if (a <= st && dr <= b) {
        if (a == 1 && b == 1) {
          ///  cout << liste_arb[care][nod];
        }
        rezultat = max(liste_arb[care][nod], rezultat);
    } else {
        int mid = (st + dr) / 2;
        if (a <= mid) Query(2 * nod, st, mid, a, b, care);
        if (b > mid) Query(2 * nod+1, mid+1, dr, a, b, care);
    }
}

int Quer_arb(int care, int a, int b) {
    rezultat = 0;
    Query(1, 1, liste[care].size(), a, b, care);
    return rezultat;
}

void Update_arb(int care, int poz, int val) {
    Update(1, 1, liste[care].size(), care, poz, val);
}

void heavypath(int nod, int &k) {
    int curent = k;
    if (first[k] == 0) {
        first[k] = nod;
    }
    lst[k] = nod;
    hp_id[nod] = k;
    liste[k].push_back(nod);
    poz[nod] = liste[k].size();

    for (auto &y:vec[nod]) {
        if (y != parent[nod]) {
            if (sz[y] > sz[nxt[nod]]) {
                nxt[nod] = y;
            }
        }
    }

    if (nxt[nod] != 0) {
        heavypath(nxt[nod], k);
    }

    for (auto &y:vec[nod]) {
        if (y != parent[nod] && y != nxt[nod]) {
            k++;
            adancime[k] = adancime[curent] + 1;
            heavypath(y, k);
        }
    }
}

void DFS(int nod, int par=-1) {
    parent[nod] = par;
    sz[nod] = 1;
    for (auto &y:vec[nod]) {
        if (y != par) {
            DFS(y, nod);
            sz[nod] += sz[y];
        }
    }
}

int query_mare(int x, int y) {
    int rasp = 0;
    while (hp_id[x] != hp_id[y]) {
        if (adancime[hp_id[x]] > adancime[hp_id[y]]) {
            rasp = max(rasp, Quer_arb(hp_id[x], 1, poz[x]));
            x = parent[first[hp_id[x]]];
        } else {
            rasp = max(rasp, Quer_arb(hp_id[y], 1, poz[y]));
            y = parent[first[hp_id[y]]];
        }
    }
    rasp = max(rasp, Quer_arb(hp_id[x], min(poz[x], poz[y]), max(poz[x], poz[y])));
    return rasp;
}

int main() {
    in >> n >> q;
    int a, b;
    for (int i=1; i<=n; i++) {
        in >> val[i];
    }
    for (int i=1; i<n; i++) {
        in >> a >> b;
        vec[a].push_back(b);
        vec[b].push_back(a);
    }
    DFS(1);
    int k = 0;
    heavypath(1, k);
    for (int i=0; i<=k; i++) {
        liste_arb[i].resize(4 * liste[i].size());
        Construieste_arbore(1, 1, liste[i].size(), i);
    }
    int op, x, y;
    while (q--) {
        in >> op >> x >> y;
        if (op == 0) {
            Update_arb(hp_id[x], poz[x], y);
        } else {
            out << query_mare(x, y) << "\n";
        }
    }
    return 0;
}