Cod sursa(job #2637071)

Utilizator Mihai145Oprea Mihai Adrian Mihai145 Data 21 iulie 2020 08:37:43
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.86 kb
#include <fstream>
#include <vector>

using namespace std;

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

const int NMAX = 1e5;

int N, M, a[NMAX + 2];
vector <int> g[NMAX + 2];

int dad[NMAX + 2], w[NMAX + 2], h[NMAX + 2];

int heavyHead[NMAX + 2];

vector <int> order;
int pos[NMAX + 2];

void dfs(int node, int dady)
{
    dad[node] = dady;
    w[node] = 1;
    h[node] = h[dady] + 1;

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

void dfsHeavy(int node)
{
    order.push_back(node);
    pos[node] = order.size();

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

        heavySon = g[node][1];
    }

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

    heavyHead[heavySon] = heavyHead[node];

    dfsHeavy(heavySon);

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

struct Aint
{
    int v[4 * NMAX];

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

        int mid = (st + dr) >> 1;

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

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

    int Query(int node, int st, int dr, int l, int r)
    {
        if(r < st || l > dr)
            return 0;

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

        int mid = (st + dr) >> 1;

        return max(Query(2 * node, st, mid, l, r), Query(2 * node + 1, mid + 1, dr, l, r));
    }
};

Aint aint;

int Query(int x, int y)
{
    if(heavyHead[x] == heavyHead[y])
    {
        int st = pos[x], dr = pos[y];

        if(st > dr)
            swap(st, dr);

        return aint.Query(1, 1, N, st, dr);
    }

    if(h[heavyHead[x]] > h[heavyHead[y]])
    {
        int ans1 = aint.Query(1, 1, N, pos[heavyHead[x]], pos[x]);
        return max(ans1, Query(dad[heavyHead[x]], y));
    }

    int ans1 = aint.Query(1, 1, N, pos[heavyHead[y]], pos[y]);
    return max(ans1, Query(dad[heavyHead[y]], x));
}

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

    for(int i = 1; i <= N; i++)
        cin >> a[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, pos[i], a[i]);

    for(int i = 1; i <= M; i++)
    {
        int t, x, y;
        cin >> t >> x >> y;

        if(t == 0)
            aint.Update(1, 1, N, pos[x], y);
        else
            cout << Query(x, y) << '\n';
    }

    return 0;
}