Cod sursa(job #2910556)

Utilizator toma_ariciuAriciu Toma toma_ariciu Data 22 iunie 2022 10:16:06
Problema Heavy Path Decomposition Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.97 kb
/// Preset de infoarena
#include <fstream>
#include <iostream>
#include <vector>

using namespace std;

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

const int maxN = 100005;
int n, q;
int val[maxN], sz[maxN], lant[maxN], nrp, pozlant[maxN], p[maxN];
int depth[maxN], euler[2 * maxN], poz_euler[maxN], ind_euler, log2[2 * maxN], rmq[20][2 * maxN];
vector <int> path[maxN], aint[maxN];
vector <int> G[maxN];

void dfs(int nod, int tata)
{
    int nxt = 0;
    sz[nod] = 1;
    euler[++ind_euler] = nod;
    poz_euler[nod] = ind_euler;
    depth[nod] = depth[tata] + 1;
    p[nod] = tata;
    for(int vecin : G[nod])
    {
        if(vecin == tata)
            continue;
        dfs(vecin, nod);
        sz[nod] += sz[vecin];
        if(sz[vecin] > sz[nxt])
            nxt = vecin;
        euler[++ind_euler] = nod;
    }
    if(sz[nod] == 1)
        lant[nod] = ++nrp;
    else
        lant[nod] = lant[nxt];
    path[lant[nod]].push_back(nod);
    pozlant[nod] = path[lant[nod]].size();
}

bool cmp(int a, int b)
{
    return (depth[a] < depth[b]);
}

int get_lca(int x, int y)
{
    int st, dr, log;
    st = poz_euler[x];
    dr = poz_euler[y];
    if(st > dr)
        swap(st, dr);
    log = log2[dr - st + 1];
    int aux = min(rmq[log][st], rmq[log][dr - (1 << log) + 1], cmp);
    return aux;
}

void init_aint(int ind, int nod, int st, int dr)
{
    if(st == dr)
    {
        aint[ind][nod] = val[path[ind][st - 1]];
        return;
    }
    int med = (st + dr) / 2;
    init_aint(ind, 2 * nod, st, med);
    init_aint(ind, 2 * nod + 1, med + 1, dr);
    aint[ind][nod] = max(aint[ind][2 * nod], aint[ind][2 * nod + 1]);
}


void update(int ind, int nod, int st, int dr, int poz, int val)
{
    if(st == dr)
    {
        aint[ind][nod] = val;
        return;
    }
    int med = (st + dr) / 2;
    if(poz <= med)
        update(ind, 2 * nod, st, med, poz, val);
    if(med + 1 <= poz)
        update(ind, 2 * nod + 1, med + 1, dr, poz, val);
    aint[ind][nod] = max(aint[ind][2 * nod], aint[ind][2 * nod + 1]);
}

int query(int ind, int nod, int st, int dr, int qst, int qdr)
{
    if(qst <= st && dr <= qdr)
        return aint[ind][nod];
    int med = (st + dr) / 2, aux = -1;
    if(qst <= med)
        aux = max(aux, query(ind, 2 * nod, st, med, qst, qdr));
    if(med + 1 <= qdr)
        aux = max(aux, query(ind, 2 * nod + 1, med + 1, dr, qst, qdr));
    return aux;
}


int get_ans(int x, int y)
{
    if(depth[x] < depth[y])
        swap(x, y);
    int aux = -1;
    while(lant[x] != lant[y])
    {
        aux = max(aux, query(lant[x], 1, 1, path[lant[x]].size(), pozlant[x], path[lant[x]].size()));
        x = p[path[lant[x]].back()];
    }
    aux = max(aux, query(lant[x], 1, 1, path[lant[x]].size(), pozlant[x], pozlant[y]));
    return aux;
}

int main()
{
    fin >> n >> q;
    for(int i = 1; i <= n; i++)
        fin >> val[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);
    depth[0] = 0x3f3f3f3f;
    for(int i = 2; i <= ind_euler; i++)
        log2[i] = log2[i / 2] + 1;
    for(int i = 1; i <= ind_euler; i++)
        rmq[0][i] = euler[i];
    for(int j = 1; (1 << j) <= ind_euler; j++)
        for(int i = 1; i + (1 << (j - 1)) - 1 <= ind_euler; i++)
            rmq[j][i] = min(rmq[j - 1][i], rmq[j - 1][i + (1 << (j - 1))], cmp);
    for(int i = 1; i <= nrp; i++)
    {
        aint[i].resize(4 * (path[i].size() + 1));
        init_aint(i, 1, 1, path[i].size());
    }
    for(int i = 1; i <= q; i++)
    {
        int op, x, y;
        fin >> op >> x >> y;
        if(op == 0)
            update(lant[x], 1, 1, path[lant[x]].size(), pozlant[x], y);
        if(op == 1)
        {
            int ans, lca = get_lca(x, y);
            ans = max(get_ans(x, lca), get_ans(y, lca));
            fout << ans << '\n';
        }
    }
    return 0;
}