Cod sursa(job #2715788)

Utilizator Mihai145Oprea Mihai Adrian Mihai145 Data 4 martie 2021 11:01:16
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.01 kb
#include <fstream>
#include <vector>

using namespace std;

///dfs normal pt calcularea de dad, weight, level

///dfsHeavy pt calcularea lanturilor grele:
///1) calculam heavyHead[node] = capatul lantului greu in care se afla nodul node
///2) calculam dfsOrder[node] = pozitia nodului node in sirul dfsGreu

///AINT pentru update/query
///1) la update, adaugam V la dfsOrder[node]
///2) la query, gasim lca-ul celor 2 noduri urcand in sus pe lanturile grele

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

const int NMAX = 100000;

///AINT///

struct arbint
{
    int v[4 * NMAX];

    void Update(int node, int l, int r, int pos, int val)
    {
        if(l == r)
        {
            v[node] = val;
            return;
        }

        int mid = (l + r) >> 1;

        if(pos <= mid)
            Update(2 * node, l, mid, pos, val);
        else
            Update(2 * node + 1, mid + 1, r, pos, val);

        v[node] = max(v[2 * node], v[2 * node + 1]);
    }

    int Query(int node, int l, int r, int st, int dr)
    {
        if(st <= l && r <= dr)
            return v[node];

        int mid = (l + r) >> 1;

        if(dr <= mid)
            return Query(2 * node, l, mid, st, dr);
        else if(st >= mid + 1)
            return Query(2 * node + 1, mid + 1, r, st, dr);
        else
            return max(Query(2 * node, l, mid, st, mid),
                       Query(2 * node + 1, mid + 1, r, mid + 1, dr));
    }
};
arbint aint;

///AINT///

int N, M, vals[NMAX + 5];
vector <int> g[NMAX + 5], order;

int dad[NMAX + 5], weight[NMAX + 5], level[NMAX + 5];
int heavyHead[NMAX + 5], dfsOrder[NMAX + 5];

void dfs(int node, int _dad)
{
    dad[node] = _dad;
    level[node] = level[_dad] + 1;
    weight[node] = 1;

    for(auto it : g[node])
        if(it != _dad)
        {
            dfs(it, node);
            weight[node] += weight[it];
        }
}

void dfsHeavy(int node)
{
    dfsOrder[node] = (int)order.size() + 1;
    order.push_back(node);

    if(g[node].size())
    {
        int heavySon = g[node][0];
        if(heavySon == dad[node])
        {
            if(g[node].size() >= 2)
                heavySon = g[node][1];
            else
                return ;
        }

        for(auto it : g[node])
            if(it != dad[node] && weight[it] > weight[heavySon])
                heavySon = it;

        heavyHead[heavySon] = heavyHead[node];
        dfsHeavy(heavySon);

        for(auto it : g[node])
            if(it != dad[node] && it != heavySon)
                dfsHeavy(it);
    }
}

int QueryLca(int x, int y)
{
    ///x si y sunt pe acelasi lant greu
    if(heavyHead[x] == heavyHead[y])
    {
        if(dfsOrder[x] > dfsOrder[y])
            swap(x, y);

        return aint.Query(1, 1, N, dfsOrder[x], dfsOrder[y]);
    }

    if(level[dad[heavyHead[x]]] > level[dad[heavyHead[y]]])
    {
        int st = min(dfsOrder[x], dfsOrder[heavyHead[x]]),
            dr = max(dfsOrder[x], dfsOrder[heavyHead[x]]);
        return max(aint.Query(1, 1, N, st, dr),
                   QueryLca(dad[heavyHead[x]], y));
    }

    int st = min(dfsOrder[y], dfsOrder[heavyHead[y]]),
        dr = max(dfsOrder[y], dfsOrder[heavyHead[y]]);

    return max(aint.Query(1, 1, N, st, dr),
               QueryLca(x, dad[heavyHead[y]]));
}

int main()
{
    cin >> N >> M;

    for(int i = 1; i <= N; i++)
        cin >> vals[i];

    for(int i = 1; i < N; i++)
    {
        int x, y;
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    dfs(1, 0);

    for(int i = 1; i <= N; i++)
        heavyHead[i] = i;
    dfsHeavy(1);

    for(int i = 1; i <= N; i++)
        aint.Update(1, 1, N, dfsOrder[i], vals[i]);

    for(int i = 1; i <= M; i++)
    {
        int c, x, y;

        cin >> c >> x >> y;

        if(c == 0)
            aint.Update(1, 1, N, dfsOrder[x], y);
        else
            cout << QueryLca(x, y) << '\n';
    }

    return 0;
}