Cod sursa(job #3143973)

Utilizator BuzdiBuzdugan Rares Andrei Buzdi Data 3 august 2023 16:59:52
Problema Heavy Path Decomposition Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.45 kb
 #include <fstream>
// #include <iostream>
#include <vector>

using namespace std;

 ifstream cin("heavypath.in");
 ofstream cout("heavypath.out");

const int NMAX = 1e5 + 5;

class AINT
{
private:
    int n = 0;
    vector<int> aint;

    void Build(int node, int left, int right, vector<int>& a)
    {
        if (left == right)
            aint[node] = a[left];
        else
        {
            int mid = (left + right) / 2;
            Build(node * 2, left, mid, a);
            Build(node * 2 + 1, mid + 1, right, a);
            aint[node] = max(aint[node * 2], aint[node * 2 + 1]);
        }
    }

    void Update(int node, int left, int right, int pos, int value)
    {
        if (left == right)
            aint[node] = value;
        else
        {
            int mid = (left + right) / 2;
            if (pos <= mid)
                Update(node * 2, left, mid, pos, value);
            else
                Update(node * 2 + 1, mid + 1, right, pos, value);
            aint[node] = max(aint[node * 2], aint[node * 2 + 1]);
        }
    }

    int Query(int node, int left, int right, int Qleft, int Qright)
    {
        if (left >= Qleft && right <= Qright)
            return aint[node];
        int mid = (left + right) / 2;
        if (mid >= Qright)
            return Query(node * 2, left, mid, Qleft, Qright);
        if (mid + 1 <= Qleft)
            return Query(node * 2 + 1, mid + 1, right, Qleft, Qright);

        int LeftNode = Query(node * 2, left, mid, Qleft, Qright);
        int RightNode = Query(node * 2 + 1, mid + 1, right, Qleft, Qright);

        return max(LeftNode, RightNode);
    }

public:
    void Build(vector<int>& a)
    {
        n = a.size() - 1;
        aint.resize(4 * n);
        Build(1, 1, n, a);
    }
    void Update(int pos, int value)
    {
        Update(1, 1, n, pos, value);
    }
    int Query(int Qleft, int Qright)
    {
        return Query(1, 1, n, Qleft, Qright);
    }
};

int n, m;
int Value[NMAX + 1];
vector<int> G[NMAX + 1];

int H[NMAX + 1];
int Parent[NMAX + 1];
int W[NMAX + 1];

int HeavyEdge[NMAX + 1];
vector<int> Path[NMAX + 1];
int Head[NMAX + 1];
int num_Paths = 1;
int WhatPath[NMAX + 1];
int PosPath[NMAX + 1];

AINT aint_Path[NMAX + 1];

void DFS(int Node, int Dad)
{
    H[Node] = H[Dad] + 1;
    Parent[Node] = Dad;

    int max_W = 0;
    for (int Child : G[Node])
        if (Child != Dad)
        {
            DFS(Child, Node);
            if (W[Child] > max_W)
            {
                max_W = W[Child];
                HeavyEdge[Node] = Child;
            }
            W[Node] += W[Child];
        }
    W[Node]++;
}

void InitializePaths()
{
    for (int i = 1; i <= NMAX; i++)
        Path[i].push_back(0);
}

void CreatePaths(int Node, int Curent_Head, int Dad)
{
    Head[Node] = Curent_Head;
    Path[num_Paths].push_back(Value[Node]);
    WhatPath[Node] = num_Paths;
    PosPath[Node] = Path[num_Paths].size() - 1;

    if (HeavyEdge[Node])
        CreatePaths(HeavyEdge[Node], Curent_Head, Node);

    for (int Child : G[Node])
        if (Child != Dad && Child != HeavyEdge[Node])
        {
            num_Paths++;
            CreatePaths(Child, Child, Node);
        }
}

int Query(int x, int y)
{
    int max_value = 0;
    while (Head[x] != Head[y])
    {
        if (H[Head[x]] > H[Head[y]])
            swap(x, y);
        int max_value_path = aint_Path[WhatPath[Head[y]]].Query(PosPath[Head[y]], PosPath[y]);
        max_value = max(max_value, max_value_path);
        y = Parent[Head[y]];
    }

    if (H[x] > H[y])
        swap(x, y);
    int max_value_path = aint_Path[WhatPath[y]].Query(PosPath[x], PosPath[y]);
    max_value = max(max_value, max_value_path);
    return max_value;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> Value[i];

    for (int i = 1; i <= n - 1; i++)
    {
        int a, b;
        cin >> a >> b;

        G[a].push_back(b);
        G[b].push_back(a);
    }

    DFS(1, 0);
    InitializePaths();
    CreatePaths(1, 1, 0);

    for (int i = 1; i <= num_Paths; i++)
        aint_Path[i].Build(Path[i]);

    while (m--)
    {
        int tip, x, y;
        cin >> tip >> x >> y;

        if (tip == 0)
            aint_Path[WhatPath[x]].Update(PosPath[x], y);
        else
            cout << Query(x, y) << '\n';
    }


    return 0;
}