Cod sursa(job #3364186)

Utilizator nicoleta_iancuIancu Nicoleta nicoleta_iancu Data 31 august 2026 11:23:21
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.14 kb

#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
struct AINT {
    vector<int>aint;
    void resizeAint(int n) {
        int log_sup = (int)log2(n);
        if ((1 << log_sup) < n)
        {
            log_sup++;
        }
        aint.resize(1 << (1 + log_sup), 0);
    }
    void updateAint(int pozTree, int st, int dr, int pozUpdate, int valUpdate) {
        if (st == dr) {
            aint[pozTree] = valUpdate;
            return;
        }
        int leftChild = 2 * pozTree;
        int rightChild = 2 * pozTree + 1;
        int mij = (st + dr) / 2;
        if (pozUpdate <= mij) {
            updateAint(leftChild, st, mij, pozUpdate, valUpdate);
        }
        else {
            updateAint(rightChild, mij + 1, dr, pozUpdate, valUpdate);
        }
        aint[pozTree] = max(aint[leftChild], aint[rightChild]);
    }
    int queryAint(int pozTree, int st, int dr, int stFind, int drFind) {
        if (st >= stFind && dr <= drFind) {
            return aint[pozTree];
        }
        int leftChild = 2 * pozTree;
        int rightChild = 2 * pozTree + 1;
        int mij = (st + dr) / 2;
        int rightAnswr = 0;
        int leftAnswr = 0;
        if (stFind <= mij) {
            leftAnswr = queryAint(leftChild, st, mij, stFind, drFind);
        }
        if (drFind > mij) {
            rightAnswr = queryAint(rightChild, mij + 1, dr, stFind, drFind);
        }
        return max(leftAnswr, rightAnswr);
    }
};
struct lant {
    int depthStart;
    int depthEnd;
    int rootNode;
    lant() :depthStart(0), depthEnd(0), rootNode(0) {};
};
vector<lant>l;
int nrLant = 0;
vector<int>subTreeSize;
vector<int>indexLant;
vector<int>depth;   
vector<int>newIdx;
vector<int>tata;
vector<vector<int>>arb;
void DFS(int nodCrt, int father,int crtDepth) {
    tata[nodCrt] = father;
    subTreeSize[nodCrt] = 1;
    depth[nodCrt] = crtDepth;
    if (arb[nodCrt].size()==1 && father != -1) {
        indexLant[nodCrt] = nrLant;
        l.push_back(lant());
        l.back().depthStart = crtDepth;
        l.back().depthEnd = crtDepth;
        l.back().rootNode = nodCrt;
        nrLant++;
    }
    int maxSz = 0;
    int idxCopil = 1e6+1;//cu ce copil unim

    for (auto i : arb[nodCrt]) {
        if (i != father) {
            DFS(i, nodCrt, crtDepth + 1);
            subTreeSize[nodCrt] += subTreeSize[i];
            if (subTreeSize[i] > maxSz || (subTreeSize[i] == maxSz && i>idxCopil)) {
                maxSz = subTreeSize[i];
                idxCopil = i;
            }
        }
    }
    if (idxCopil != 1e6+1) {
        indexLant[nodCrt] = indexLant[idxCopil];
        l[indexLant[idxCopil]].rootNode = nodCrt;
        l[indexLant[idxCopil]].depthStart = crtDepth;
    }
}
int cnt = 1;
void reorderNodes(int nodCrt,int father) {
    newIdx[nodCrt] = cnt;
    ++cnt;
    vector<pair<int, int>>maxSize;
    for (auto i : arb[nodCrt]) {
        if (i != father) {
            maxSize.push_back(make_pair(subTreeSize[i], i));
        }
    }
    sort(maxSize.begin(), maxSize.end(),greater<pair<int,int>>());
    for (int i = 0; i < maxSize.size(); ++i) {
        reorderNodes(maxSize[i].second, nodCrt);
    }
}

AINT maxNode;//maxNode pe fiecare lant
int n;
int lift(int node,int depthCrt) {
    int maxi = 0;
    while (l[indexLant[node]].depthStart > depthCrt) {
        int root = l[indexLant[node]].rootNode;
        maxi = max(maxi, maxNode.queryAint(1, 1, n, newIdx[root], newIdx[node]));
        node = tata[root];
    }
    int lcaIdx = newIdx[node] - (depth[node] - depthCrt);
    maxi = max(maxi, maxNode.queryAint(1, 1, n, lcaIdx, newIdx[node]));

    return maxi;
}


int getDepthLca(int u, int v) {
    if (depth[u] < depth[v]) {
        swap(u, v);
    }
    while (indexLant[u] != indexLant[v])
    {
        if (l[indexLant[u]].depthStart >= l[indexLant[v]].depthStart) {
            u = tata[l[indexLant[u]].rootNode];
        }
        else {
            v = tata[l[indexLant[v]].rootNode];
        }
    }
    return min(depth[v], depth[u]);
}

int main()
{
    int q;
    fin >> n>>q;
    vector<int>v(n+1);
    for (int i = 1; i <= n; ++i) {
        fin >> v[i];
    }
    arb.resize(n + 1);
    indexLant.resize(n + 1);
    subTreeSize.resize(n + 1);
    depth.resize(n + 1);
    newIdx.resize(n + 1);
    tata.resize(n + 1);
    int nod1,nod2;
    for (int i = 0; i < n - 1; ++i) {
        fin >> nod1 >> nod2;
        arb[nod1].push_back(nod2);
        arb[nod2].push_back(nod1);
    }

    DFS(1, 0, 0);

    reorderNodes(1, -1);
    maxNode.resizeAint(n + 2);
    for (int i = 1; i <= n; ++i) {
        maxNode.updateAint(1, 1, n, newIdx[i], v[i]);
    }
    int type, x, y;
    for (int i = 0; i < q; ++i) {
        fin >> type >> x >> y;
        if (type == 0) {
            maxNode.updateAint(1, 1, n, newIdx[x], y);
        }else{

            int depthLCA = getDepthLca(x, y);
            fout << max(lift(x, depthLCA), lift(y, depthLCA))<<"\n";
        }
    }
    return 0;
}
//=^..^=