Cod sursa(job #2733365)

Utilizator Iulia25Hosu Iulia Iulia25 Data 30 martie 2021 12:04:20
Problema Heavy Path Decomposition Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.43 kb
#include <fstream>
#include <algorithm>
#include <vector>

using namespace std;

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

const int N = 1e5 + 5;

int a[4 * N];
int subarb[N], lant[N], poz[N], id[N], ad[N], val[N];
int tata[N][22];

int n;
int nr_noduri_viz, poz_aint, start = 1;

vector <int> v[N];

void dfs(int nod, int adancime)   {
    id[nod] = ++nr_noduri_viz;
    subarb[nod] = 1;
    ad[nod] = adancime;
    for (auto it : v[nod])  {
        if (!id[it])    {
            dfs(it, adancime + 1);
            subarb[nod] += subarb[it];
            tata[it][0] = nod;
        }
    }
}

bool cmp_vecini(int x, int y)   {
    return subarb[x] > subarb[y];
}

void create_segments(int nod, int Lant)  {
    a[++poz_aint] = val[nod];
    poz[nod] = poz_aint; //pozitia nodului nod in aint
    lant[nod] = Lant;
    sort (v[nod].begin(), v[nod].end(), cmp_vecini);
    bool lant_curent = true;
    for (auto it : v[nod])  {
        if (!poz[it])   {
            if (!lant_curent)
                create_segments(it, it);
            else    {
                create_segments(it, nod);
                lant_curent = false;
            }
        }
    }
}

namespace aint  {

void build()    {
    for (int i = start - 1; i; --i) {
        a[i] = max(a[i + i], a[i + i + 1]);
    }
}

void Update(int nod)    {
    a[nod] = max(a[nod + nod], a[nod + nod + 1]);
    if (nod > 1)
        Update(nod / 2);
}

int Query(int st, int dr)   {
    int ans = 0;
    if (st & 1)
        ans = a[st++];
    if (!(dr & 1))
        ans = max(ans, a[dr--]);
    if (st < dr)
        ans = max(ans, Query(st / 2, dr / 2));
    return ans;
}
}

namespace stramosi  {
void rmq()  {
    for (int i = 1; i <= 20; ++i)   {
        for (int j = 1; j <= n; ++j)    {
            tata[j][i] = tata[tata[j][i - 1]][i - 1];
        }
    }
}

int find_daddy(int nod, int nivel)  {
    for (int i = 1, j = 0; i <= nivel; i <<= 1, ++j)    {
        if (i & nivel)
            nod = tata[nod][j];
    }
    return nod;
}

int lca(int x, int y)   {
    if (ad[x] > ad[y])
        x = find_daddy(x, ad[x] - ad[y]);
    if (ad[y] > ad[x])
        y = find_daddy(y, ad[y] - ad[x]);
    if (x == y)
        return x;
    int ans = 1;
    for (int i = 20; i >= 0; --i)   {
        if (tata[x][i] != tata[y][i])   {
            x = tata[x][i];
            y = tata[y][i];
        } else ans = tata[x][i];
    }
    return ans;
}
}

int Query(int nod, int t)    {
    int ans = 0;
    while(true) {
        int l = lant[nod];
        if (ad[l] <= ad[t]) {
            l = t;
            ans = max(aint::Query(poz[l], poz[nod]), ans);
            break;
        }
        ans = max(aint::Query(poz[l], poz[nod]), ans);
        nod = tata[l][0];
    }
    return ans;
}

int main()  {
    int m, x, y, type;
    cin >> n >> m;
    for (int i = 1; i <= n; ++i)
        cin >> val[i];
    for (int i = 1; i < n; ++i)    {
        cin >> x >> y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    dfs(1, 1);
    while (start < n)
        start <<= 1;
    poz_aint = start - 1;
    create_segments(1, 1);
    aint::build();
    stramosi::rmq();
    while (m--) {
        cin >> type >> x >> y;
        if (type == 0)  {
            a[poz[x]] = y;
            aint::Update(poz[x] / 2);
        } else    {
            int l = stramosi::lca(x, y);
//            cout << Query(x, l) << ' ';
//            cout << Query(y, l) << '\n';
            cout << max(Query(x, l), Query(y, l)) << '\n';
        }
    }
    return 0;
}