Cod sursa(job #2604409)

Utilizator AlexandruGabrielAliciuc Alexandru AlexandruGabriel Data 22 aprilie 2020 16:49:54
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.37 kb
#include <bits/stdc++.h>

using namespace std;

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

const int N = 100005, LOG = 18;
int n, q;
vector <int> L[N];
bool viz[N];
int value[N], path[N], pos[N], pathParent[LOG], level[N];
int dp[N], cntPaths, len[LOG];
int aint[LOG][4 * N];

void updateAint(int p, int node, int st, int dr, int targetPos, int val)
{
    if (st == dr)
    {
        aint[p][node] = val;
        return;
    }

    int mij = (st + dr) / 2;

    if (targetPos <= mij)
        updateAint(p, 2 * node, st, mij, targetPos, val);
    else
        updateAint(p, 2 * node + 1, mij + 1, dr, targetPos, val);

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

int queryAint(int p, int node, int st, int dr, int lft, int rgt)
{
    if (st >= lft && dr <= rgt)
        return aint[p][node];
    else
    {
        int mij = (st + dr) / 2;

        int q1 = 0, q2 = 0;
        if (lft <= mij)
            q1 = queryAint(p, 2 * node, st, mij, lft, rgt);
        if (rgt >= mij + 1)
            q2 = queryAint(p, 2 * node + 1, mij + 1, dr, lft, rgt);

        return max(q1, q2);
    }
}

int Query(int x, int y)
{
    int ans = 0;
    bool ok = 0;

    while (!ok)
    {
        if (level[pathParent[x]] > level[pathParent[y]])
            swap(x, y);

        if (path[x] == path[y])
        {
            int lft = min(pos[x], pos[y]);
            int rgt = max(pos[x], pos[y]);
            ans = max(ans, queryAint(path[x], 1, 1, len[path[x]], lft, rgt));

            ok = 1;
        }
        else
        {
            ans = max(ans, queryAint(path[x], 1, 1, len[path[x]], 1, pos[x]));
            x = pathParent[path[x]];
        }
    }

    return ans;
}


void DFS(int node, int task)
{
    viz[node] = 1;

    if (task == 1)
    {
        if (L[node].size() == 1 && node != 1)
        path[node] = ++cntPaths;

        for (int nextNode : L[node])
            if (!viz[nextNode])
            {
                int maxim = 0;
                level[nextNode] = level[node] + 1;
                DFS(nextNode, task);

                dp[node] += dp[nextNode];
                if (maxim < path[nextNode])
                {
                    maxim = path[nextNode];
                    path[node] = path[nextNode];
                }
            }
        dp[node]++;

        for (int nextNode : L[node])
        {
            if (path[node] != path[nextNode])
                pathParent[path[nextNode]] = node;
        }
    }
    else
    {
        pos[node] = ++len[path[node]];

        for (int nextNode : L[node])
            if (!viz[nextNode])
                DFS(nextNode, task);

        updateAint(path[node], 1, 1, len[path[node]], pos[node], value[node]);
    }
}

int main()
{
    fin >> n >> q;
    for (int i = 1; i <= n; i++)
        fin >> value[i];
    for (int i = 1; i < n; i++)
    {
        int a, b;
        fin >> a >> b;
        L[a].push_back(b);
        L[b].push_back(a);
    }

    level[1] = 1;
    DFS(1, 1);
    for (int i = 1; i <= n; i++)
        viz[i] = 0;
    DFS(1, 2);

    while(q--)
    {
        int op, x, y;
        fin >> op >> x >> y;

        if (op == 0)
            updateAint(path[x], 1, 1, len[path[x]], pos[x], y);
        else
            fout << Query(x, y) << "\n";
    }

    return 0;
}