Cod sursa(job #2733393)

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

using namespace std;

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

const int N = 1e5 + 5;

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

int n;
int poz_aint, start = 1;

int nrpasi = 0;

vector <int> v[N];

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

bool cmp_vefini(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_vefini);
    bool lant_curent = true;
    for (auto it : v[nod])  {
        if (!poz[it])   {
            if (!lant_curent)
                create_segments(it, it);
            else    {
                create_segments(it, lant[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--]);
    int aux = 0;
    if (st < dr)
        aux = Query(st / 2, dr / 2);
    return max(aux, 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 = 19; 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 l)   {
    if (lant[l] == lant[nod])
        return aint::Query(poz[l], poz[nod]);
    int aux = aint::Query(poz[lant[nod]], poz[nod]);
    int aux2 = Query(tata[lant[nod]][0], l);
    return max(aux, aux2);
}

int main()  {
    int m, x, y, type;
    fin >> n >> m;
    for (int i = 1; i <= n; ++i)
        fin >> val[i];
    for (int i = 1; i < n; ++i)    {
        fin >> 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--) {
        fin >> type >> x >> y;
        if (type == 0)  {
            a[poz[x]] = y;
            aint::Update(poz[x] / 2);
        } else    {
            int l = stramosi::lca(x, y);
//            fout << Query(x, l) << ' ';
//            fout << Query(y, l) << '\n';
            nrpasi = 0;
            int ans = Query(x, l);
            int aux = Query(y, l);
//            if (nrpasi > 1000)
//                return l;
            fout << max(ans, aux) << '\n';
        }
    }
    return 0;
}