Cod sursa(job #3362718)

Utilizator EricDimiCismaru Eric-Dimitrie EricDimi Data 11 august 2026 15:31:36
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.45 kb
#include <fstream>
#include <algorithm>
#include <vector>

using namespace std;

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

const int MAX_N = 100000;

inline int max(int x, int y)
{
    return (x > y) ? x : y;
}

inline void swap(int& x, int& y)
{
    x ^= y ^= x ^= y;
}

int NextPow2(int val)
{
    --val;
    val |= val >> 1;
    val |= val >> 2;
    val |= val >> 4;
    val |= val >> 8;
    val |= val >> 16;
    return val + 1;
}

vector<int> adj[MAX_N + 1],
            path[MAX_N + 1];
int val[MAX_N + 1],
    depth[MAX_N + 1],
    subSize[MAX_N + 1];
int parent[MAX_N + 1],
    idx[MAX_N + 1],
    pos[MAX_N + 1],
    len[MAX_N + 1];
int n, q, pathsCount;

struct SegmentTree
{
    int tree[MAX_N << 2];

    void Build(int pathIdx, int delta)
    {
        int pathSize = len[pathIdx],
            n = NextPow2(pathSize);

        for(int i = 0; i < pathSize; i++)
            tree[i + n + delta] = val[path[pathIdx][i]];
        for(int i = n - 1; i > 0; i--)
            tree[i + delta] = max(tree[(i << 1) + delta], tree[(i << 1 | 1) + delta]);
    }

    void Update(int pathIdx, int pos, int val, int delta)
    {
        int pathSize = len[pathIdx],
            n = NextPow2(pathSize);

        pos += n - 1;
        tree[pos + delta] = val;

        pos >>= 1;
        while(pos > 0)
        {
            tree[pos + delta] = max(tree[(pos << 1) + delta], tree[(pos << 1 | 1) + delta]);
            pos >>= 1;
        }
    }

    int Query(int pathIdx, int left, int right, int delta)
    {
        int pathSize = len[pathIdx],
            n = NextPow2(pathSize);
        int res = 0;

        left += n - 1;
        right += n - 1;

        while(left <= right)
        {
            if(left & 1)
            {
                res = max(res, tree[left + delta]);
                left++;
            }
            if(!(right & 1))
            {
                res = max(res, tree[right + delta]);
                right--;
            }

            left >>= 1;
            right >>= 1;
        }

        return res;
    }
};
SegmentTree segTree;
int delay[MAX_N + 1];

void Read()
{
    fin >> n >> q;
    for(int i = 1; i <= n; i++)
        fin >> val[i];
    for(int i = 1; i < n; i++)
    {
        int x, y;
        fin >> x >> y;
        adj[x].push_back(y);
        adj[y].push_back(x);
    }
}

void DFS(int node, int father)
{
    bool leaf = true;
    int heavySon = -1;

    depth[node] = 1 + depth[father];
    subSize[node] = 1;

    for(int son : adj[node])
    {
        if(son == father)
            continue;

        DFS(son, node);

        leaf = false;
        subSize[node] += subSize[son];
        if(heavySon == -1 || subSize[heavySon] < subSize[son])
            heavySon = son;
    }

    if(leaf)
    {
        ++pathsCount;
        path[pathsCount].push_back(node);
        idx[node] = pathsCount;
        return;
    }

    path[idx[heavySon]].push_back(node);
    idx[node] = idx[heavySon];

    for(int son : adj[node])
    {
        if(son == father || son == heavySon)
            continue;
        parent[idx[son]] = node;
    }
}

void MakePaths()
{
    for(int i = 1; i <= pathsCount; i++)
    {
        reverse(path[i].begin(), path[i].end());
        len[i] = (int)path[i].size();

        int ind = 0;
        for(int node : path[i])
            pos[node] = ++ind;
        delay[i] = delay[i - 1] + (NextPow2(len[i - 1]) << 1);

        segTree.Build(i, delay[i]);
    }
}

int Query(int x, int y)
{
    int res = 0;

    while(true)
    {
        if(idx[x] == idx[y])
        {
            if(pos[x] > pos[y])
                swap(x, y);
            res = max(res, segTree.Query(idx[x], pos[x], pos[y], delay[idx[x]]));
            return res;
        }

        if(depth[parent[idx[x]]] < depth[parent[idx[y]]])
            swap(x, y);
        res = max(res, segTree.Query(idx[x], 1, pos[x], delay[idx[x]]));
        x = parent[idx[x]];
    }

    return 0;
}

void SolveQueries()
{
    while(q--)
    {
        int t, x, y;
        fin >> t >> x >> y;

        if(t == 0)
            segTree.Update(idx[x], pos[x], y, delay[idx[x]]);
        else
        if(t == 1)
            fout << Query(x, y) << '\n';
    }
}

int main()
{
    Read();
    DFS(1, 0);
    MakePaths();
    SolveQueries();

    fin.close();
    fout.close();

    return 0;
}