Cod sursa(job #3294118)

Utilizator Nasa1004Ema Nicole Gheorghe Nasa1004 Data 15 aprilie 2025 22:12:31
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.6 kb
#include <fstream>
#include <algorithm>
#include <vector>

using namespace std;
const int NMAX = 100002;

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

struct noduri {
    int val, tata = 0, depth = 0;
    int weight = 0; ///cate LANTURI
    int lant;
    int pos; ///pt reindexare
}v[NMAX];

vector <vector <int>> adj;
vector <int> l;
int n;

void dfs(int start) {
    bool ok = 0;
    for(auto nod : adj[start]) {
        if(nod == v[start].tata)
            continue;
        ok = 1;
        v[nod].depth = v[start].depth + 1;
        v[nod].tata = start;
        dfs(nod);
    }
    if(!ok) { ///frunza
        l.push_back(start);
        v[start].lant = l.size() - 1;
        v[start].weight = 1;
        return;
    }
    int maxx = 0, cnt = 0, id;
    for(auto nod : adj[start]) {
        if(nod == v[start].tata)
            continue;
        if(v[nod].weight > maxx) {
            maxx = v[nod].weight;
            cnt = 1;
            id = nod;
        }
        else if(v[nod].weight == maxx)
            cnt++;
    }
    v[start].weight = maxx;
    v[start].lant = v[id].lant;
    l[v[id].lant] = start;
    if(cnt > 1)
        v[start].weight++;
}
bool cmp(const int &a, const int &b) {
    if(v[a].lant != v[b].lant)
        return v[a].lant < v[b].lant;
    return v[a].depth < v[a].depth; ///ala mai de sus e PRIMUL
}
vector <int> topo;
void reorder() { ///ord pt aint
    for(int i = 1; i <= n; i++)
        topo.push_back(i);
    sort(topo.begin(), topo.end(), cmp);
    for(int i = 0; i < n; i++)
        v[topo[i]].pos = i + 1;
}

int aint[4 * NMAX];
void build(int nod, int st, int dr) {
    if(st == dr) {
        aint[nod] = v[topo[st - 1]].val;
        return;
    }
    int mid = (st + dr) / 2;
    build(2 * nod, st, mid);
    build(2 * nod + 1, mid + 1, dr);
    aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
}
void update(int nod, int st, int dr, int pos, int val) {
    if(st == dr) {
        aint[nod] = val;
        return;
    }
    int mid = (st + dr) / 2;
    if(pos <= mid)
        update(2 * nod, st, mid, pos, val);
    else
        update(2 * nod + 1, mid + 1, dr, pos, val);
    aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
}
int query(int nod, int st, int dr, int pos1, int pos2) {
    if(st == pos1 && dr == pos2)
        return aint[nod];
    int mid = (st + dr) / 2, ans = 0;
    if(pos1 <= mid)
        ans = query(2 * nod, st, mid, pos1, min(mid, pos2));
    if(mid < pos2)
        ans = max(ans, query(2 * nod + 1, mid + 1, dr, max(mid + 1, pos1), pos2));
    return ans;
}

int solvepath(int a, int b) {
    int ans = 0;
    while(v[a].lant != v[b].lant) {
        int nr1 = l[v[a].lant], nr2 = l[v[b].lant];
        if(v[nr1].depth < v[nr2].depth) {
            swap(a, b);
            swap(nr1, nr2);
        }
        ans = max(ans, query(1, 1, n, v[nr1].pos, v[a].pos));
        a = v[nr1].tata;
    }
    if(v[a].depth < v[b].depth)
        swap(a, b);
    ans = max(ans, query(1, 1, n, v[b].pos, v[a].pos));
    return ans;
}

int main()
{
    int m;
    cin >> n >> m;
    adj.resize(n + 1);
    for(int i = 1; i <= n; i++)
        cin >> v[i].val;
    for(int i = 1; i < n; i++) {
        int a, b;
        cin >> a >> b;
        adj[a].push_back(b);
        adj[b].push_back(a);
    }
    dfs(1);
    reorder();
    build(1, 1, n);
    while(m--) {
        bool tip;
        int a, b;
        cin >> tip >> a >> b;
        if(!tip)
            update(1, 1, n, v[a].pos, b);
        else
            cout << solvepath(a, b) << '\n';
    }
    return 0;
}