Cod sursa(job #2629253)

Utilizator trifangrobertRobert Trifan trifangrobert Data 19 iunie 2020 17:39:58
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.2 kb
#include <bits/stdc++.h>

using namespace std;

const int NMAX = 100005;
int N, M, v[NMAX];
int aint[4 * NMAX];
int height[NMAX];
vector <int> paths[NMAX];
vector <int> graph[NMAX];
int cntPaths;
int pathInd[NMAX];
int pathFather[NMAX];
int pathGap[NMAX];
int weight[NMAX];
int answer;

void dfs(int node, int father)
{
    height[node] = height[father] + 1;
    weight[node] = 1;
    int heaviestSon = -1;
    for (auto& son : graph[node])
    {
        if (son != father)
        {
            dfs(son, node);
            weight[node] += weight[son];
            if (heaviestSon == -1 || weight[heaviestSon] < weight[son])
                heaviestSon = son;
        }
    }
    if (graph[node].size() == 1 && node != 1)
    {
        ++cntPaths;
        pathInd[node] = cntPaths;
        paths[cntPaths].push_back(node);
        return;
    }
    pathInd[node] = pathInd[heaviestSon];
    paths[pathInd[node]].push_back(node);
    for (auto& son : graph[node])
        if (son != father && son != heaviestSon)
            pathFather[pathInd[son]] = node;
}

int LeftSon(int node)
{
    return 2 * node;
}

int RightSon(int node)
{
    return 2 * node + 1;
}

void Build(int node, int left, int right, int gap, int path)
{
    if (left == right)
    {
        aint[node + gap] = v[paths[path][left - 1]];
        return;
    }
    int mid = (left + right) / 2;
    Build(LeftSon(node), left, mid, gap, path);
    Build(RightSon(node), mid + 1, right, gap, path);
    aint[node + gap] = max(aint[LeftSon(node) + gap], aint[RightSon(node) + gap]);
}

void HeavyLightDecomposition()
{
    dfs(1, 0);
    for (int i = 1;i <= cntPaths;++i)
    {
        reverse(paths[i].begin(), paths[i].end());
        if (i > 1)
            pathGap[i] = pathGap[i - 1] + 4 * paths[i - 1].size();
        Build(1, 1, paths[i].size(), pathGap[i], i);
    }
}

void Update(int node, int left, int right, int pos, int val, int gap)
{
    if (left == right)
    {
        aint[node + gap] = val;
        return;
    }
    int mid = (left + right) / 2;
    if (pos <= mid)
        Update(LeftSon(node), left, mid, pos, val, gap);
    else
        Update(RightSon(node), mid + 1, right, pos, val, gap);
    aint[node + gap] = max(aint[LeftSon(node) + gap], aint[RightSon(node) + gap]);
}

void Query(int node, int left, int right, int LeftQuery, int RightQuery, int gap)
{
    if (LeftQuery <= left && right <= RightQuery)
    {
        answer = max(answer, aint[node + gap]);
        return;
    }
    int mid = (left + right) / 2;
    if (LeftQuery <= mid)
        Query(LeftSon(node), left, mid, LeftQuery, RightQuery, gap);
    if (RightQuery >= mid + 1)
        Query(RightSon(node), mid + 1, right, LeftQuery, RightQuery, gap);
}

int main()
{
    ifstream fin("heavypath.in");
    ofstream fout("heavypath.out");
    fin >> N >> M;
    for (int i = 1;i <= N;++i)
        fin >> v[i];
    for (int i = 1;i < N;++i)
    {
        int u, v;
        fin >> u >> v;
        graph[u].push_back(v);
        graph[v].push_back(u);
    }
    HeavyLightDecomposition();
    while (M-- > 0)
    {
        int t, x, y;
        fin >> t >> x >> y;
        if (t == 0)
        {
            v[x] = y;
            Update(1, 1, paths[pathInd[x]].size(), height[x] - height[pathFather[pathInd[x]]], y, pathGap[pathInd[x]]);
        }
        else
        {
            answer = 0;
            while (true)
            {
                if (pathInd[x] == pathInd[y])
                {
                    if (height[x] > height[y])
                        swap(x, y);
                    Query(1, 1, paths[pathInd[x]].size(), height[x] - height[pathFather[pathInd[x]]], height[y] - height[pathFather[pathInd[y]]], pathGap[pathInd[x]]);
                    break;
                }
                if (height[pathFather[pathInd[x]]] < height[pathFather[pathInd[y]]])
                    swap(x, y);
                Query(1, 1, paths[pathInd[x]].size(), 1, height[x] - height[pathFather[pathInd[x]]], pathGap[pathInd[x]]);
                x = pathFather[pathInd[x]];
            }
            fout << answer << "\n";
        }
    }
    fin.close();
    fout.close();
    return 0;
}