Cod sursa(job #2690878)

Utilizator dimi999Dimitriu Andrei dimi999 Data 26 decembrie 2020 12:47:11
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.46 kb
#include <bits/stdc++.h>
using namespace std;

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

int values[100005];

vector <int> v[100005];

int N, M;

struct Aint
{
    int V[400005];

    void update(int node, int l, int r, int poz, int val)
    {
        if(l == r)
        {
            V[node] = val;
            return;
        }

        int mij = (l + r) / 2;

        if(poz <= mij)
            update(2 * node, l, mij, poz, val);
        else
            update(2 * node + 1, mij + 1, r, poz, val);
        V[node] = max(V[2 * node], V[2 * node + 1]);
    }

    int query(int node, int l, int r, int ql, int qr)
    {
        if(l >= ql && r <= qr)
            return V[node];

        if(l > qr || r < ql)
            return 0;

        int mij = (l + r) / 2;

        if(mij >= qr)
            return query(2 * node, l, mij, ql, qr);
        else
            if(mij < ql)
            return query(2 * node + 1, mij + 1, r, ql, qr);
        else
            return max(query(2 * node, l, mij, ql, qr), query(2 * node + 1, mij + 1, r, ql, qr));
    }

    void build(int node, int l, int r)
    {
        if(l == r)
        {
            V[node] = values[l];
            return;
        }

        int mij = (l + r) / 2;

        build(2 * node, l , mij);
        build(2 * node + 1, mij + 1, r);

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

int sz[100005], lvl[100005], dads[100005];

void dfs(int node, int dad)
{
    dads[node] = dad;
    lvl[node] = lvl[dad] + 1;

    sz[node]++;

    for(int i = 0; i < v[node].size(); i++)
        if(v[node][i] != dad)
    {
        dfs(v[node][i], node);
        sz[node] += sz[v[node][i]];
    }
}

int label[100005], head[100005], k;

void dfsGreu(int node)
{
    int fiu = v[node][0];

    label[node] = ++k;

    if(fiu == dads[node] && v[node].size() == 1)
        return;
    else
        if(fiu == dads[node])
            fiu = v[node][1];

    for(int i = 0; i < v[node].size(); i++)
        if(v[node][i] != dads[node])
            if(sz[v[node][i]] > sz[fiu])
                fiu = v[node][i];

    head[fiu] = head[node];
    dfsGreu(fiu);

    for(int i = 0; i < v[node].size(); i++)
        if(v[node][i] != dads[node] && v[node][i] != fiu)
            dfsGreu(v[node][i]);
}

int Query(int x, int y)
{
    if(head[x] == head[y])
    {
        x = label[x];
        y = label[y];

        if(x > y)
            swap(x, y);

        return aint.query(1, 1, N, x, y);
    }

    if(lvl[head[x]] > lvl[head[y]])
    {
        int ans = aint.query(1, 1, N, label[head[x]], label[x]);
        return max(ans, Query(dads[head[x]], y));
    }
    else
    {
        int ans = aint.query(1, 1, N, label[head[y]], label[y]);
        return max(ans, Query(x, dads[head[y]]));
    }
}

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

    for(int i = 1; i <= N; i++)
        fin >> values[i];

    for(int i = 1; i <= N - 1; i++)
    {
        int x, y;

        fin >> x >> y;

        v[x].push_back(y);
        v[y].push_back(x);
    }

    aint.build(1, 1, N);

    dfs(1, 0);

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

    dfsGreu(1);

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

        fin >> t >> x >> y;

        if(t == 0)
            aint.update(1, 1, N, label[x], y);
        else
            fout << Query(x, y) << '\n';
    }

    return 0;
}