Cod sursa(job #2732613)

Utilizator PatrickCplusplusPatrick Kristian Ondreovici PatrickCplusplus Data 29 martie 2021 08:40:13
Problema Heavy Path Decomposition Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.99 kb
#include <bits/stdc++.h>

using namespace std;

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

const int nmax = 100005;
int n, m, value[nmax], nivel[nmax], cnt[nmax], nrLanturi = 1, nNod[nmax], whatLant[nmax], whatPos[nmax], parent[nmax];
vector <int> G[nmax], lant[nmax], aint[nmax];

void dfs(int nod, int tata){
    int maxim = 0, nodMaxim = -1;
    cnt[nod] = 1;
    for (auto it : G[nod]){
        if (it == tata){
            continue;
        }
        parent[it] = nod;
        nivel[it] = nivel[nod] + 1;
        dfs(it, nod);
        if (cnt[it] > maxim){
            maxim = cnt[it];
            nodMaxim = it;
        }
        cnt[nod] += cnt[it];
    }
    nNod[nod] = nodMaxim ;
}

void dfs2(int nod, int tata){
    lant[whatLant[nod]].push_back(nod);
    whatPos[nod] = lant[whatLant[nod]].size() - 1;
    if (nNod[nod] != -1){
        whatLant[nNod[nod]] = whatLant[nod];
        dfs2(nNod[nod], nod);
        for (auto it : G[nod]){
            if (it == tata || it == nNod[nod]){
                continue;
            }
            dfs2(it, nod);
        }
    }
}

void Build(int l, int nod, int st, int dr){
    if (st == dr){
        aint[l][nod] = value[lant[l][st]];
        return;
    }
    int mid = (st + dr) / 2;
    Build(l, nod * 2, st, mid);
    Build(l, nod * 2 + 1, mid + 1, dr);
    aint[l][nod] = max(aint[l][nod * 2], aint[l][nod * 2 + 1]);
}

void Update(int l, int nod, int st, int dr, int pos){
    if (st == dr){
        aint[l][nod] = value[lant[l][st]];
        return;
    }
    int mid = (st + dr) / 2;
    if (pos <= mid){
        Update(l, nod * 2, st, mid, pos);
    }
    else{
        Update(l, nod * 2 + 1, mid + 1, dr, pos);
    }
    aint[l][nod] = max(aint[l][nod * 2], aint[l][nod * 2 + 1]);
}

int Query(int l, int nod, int st, int dr, int x, int y){
    if (st > y || dr < x){
        return 0;
    }
    if (st >= x && dr <= y){
        return aint[l][nod];
    }
    int mid = (st + dr) / 2;
    return max(Query(l, nod * 2, st, mid, x, y), Query(l, nod * 2 + 1, mid + 1, dr, x, y));
}

int Query2(int x, int y){
    int ans = max(value[x], value[y]);
    while (x != y){
        if (whatLant[x] == whatLant[y]){
            if (nivel[x] > nivel[y]){
                ans = max(ans, Query(whatLant[x], 1, 0, lant[whatLant[x]].size() - 1, whatPos[y], whatPos[x]));
            }
            else{
                ans = max(ans, Query(whatLant[x], 1, 0, lant[whatLant[x]].size() - 1, whatPos[x], whatPos[y]));
            }
            x = y;
        }
        else{
            int firstX = lant[whatLant[x]][0], firstY = lant[whatLant[y]][0];
            if (nivel[firstX] > nivel[firstY]){
                ans = max(ans, Query(whatLant[x], 1, 0, lant[whatLant[x]].size() - 1, 0, whatPos[x]));
                x = parent[firstX];
            }
            else{
                ans = max(ans, Query(whatLant[y], 1, 0, lant[whatLant[y]].size() - 1, 0, whatPos[y]));
                y = parent[firstY];
            }
        }
    }
    return ans;
}

int main(){
    fin >> n >> m;
    for (int i = 1; i <= n; ++i){
        fin >> value[i];
        whatLant[i] = i;
    }
    for (int i = 1; i < n; ++i){
        int x, y;
        fin >> x >> y;
        G[x].push_back(y);
        G[y].push_back(x);
    }
    dfs(1, 0);
    dfs2(1, 0);
    vector <int> viz(n + 3);
    for (int i = 1; i <= n; ++i){
        int l = whatLant[i];
        if (viz[l] == 0){
            viz[l] = 1;
            aint[l].resize(4 * lant[l].size() + 1);
            Build(l, 1, 0, lant[l].size() - 1);
        }
    }
    while (m--){
        int p, x, y;
        fin >> p >> x >> y;
        if (p == 0){
            int l = whatLant[x];
            int pos = whatPos[x];
            value[x] = y;
            Update(l, 1, 0, lant[l].size() - 1, pos);
        }
        else{
            fout << Query2(y, x) << "\n";
        }
    }
    fin.close();
    fout.close();
    return 0;
}