Cod sursa(job #2604466)

Utilizator AlexandruGabrielAliciuc Alexandru AlexandruGabriel Data 22 aprilie 2020 18:24:17
Problema Heavy Path Decomposition Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.72 kb
#include <bits/stdc++.h>

using namespace std;

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

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

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

    int mij = (st + dr) / 2;

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

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

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

        if (lft <= mij)
            queryAint(2 * node, st, mij, lft, rgt);
        if (rgt >= mij + 1)
            queryAint(2 * node + 1, mij + 1, dr, lft, rgt);

    }
}

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

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

        if (path[x] == path[y])
        {
            int lft = min(start[path[x]] + pos[x] - 1, start[path[x]] + pos[y] - 1);
            int rgt = max(start[path[x]] + pos[x] - 1, start[path[x]] + pos[y] - 1);

            queryAint(1, 1, n, lft, rgt);
            ans = max(ans, queryAns);
            queryAns = 0;

            ok = 1;
        }
        else
        {
            queryAint(1, 1, n, start[path[x]], start[path[x]] + pos[x] - 1);
            ans = max(ans, queryAns);
            x = pathParent[path[x]];
            queryAns = 0;
        }
    }

    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);
    }
}

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);

    int nextStart = 1;
    for (int node = 1; node <= n; node++)
    {
        if (!start[path[node]])
        {
            start[path[node]] = nextStart;
            nextStart = start[path[node]] + len[path[node]];
        }

        updateAint(1, 1, n, start[path[node]] + pos[node] - 1, value[node]);
    }

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

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

    return 0;
}