Cod sursa(job #2498501)

Utilizator Briana_NeaguNeagu Briana Briana_Neagu Data 23 noiembrie 2019 23:15:25
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.48 kb
#include <bits/stdc++.h>

using namespace std;

ifstream f("heavypath.in");
ofstream g("heavypath.out");

const int nmax = 100004;
int v[nmax];
pair <int, int> where[nmax];

class arbint
{
public:
    int tree[nmax * 4];
    int n, last;
    arbint(vector <int> &vec)
    {
        this -> n = vec.size();
        this -> last = vec[n - 1];
        memset(this -> tree, 0, sizeof(this -> tree));
        for (int i = 0; i < n; ++ i)
            update(i + 1, v[vec[i]]);
    }
    int findMaxFromNode(int nod)
    {
        return findMax(where[nod].second, this -> n);
    }

    int findMax(const int a, const int b)
    {
        return private_findMax(1, 1, n, a, b);
    }

    void update(const int id, const int x)
    {
        private_update(1, 1, n, id, x);
    }

private:
    int private_findMax(int nod, int i, int j, const int a, const int b)
    {

        if (a <= i && j <= b)
            return tree[nod];
        int m = (i + j) / 2;
        int ans = 0;
        if (a <= m)
            ans = max(ans, private_findMax(nod * 2, i, m, a, b));
        if (b > m)
            ans = max(ans, private_findMax(nod * 2 + 1, m + 1, j, a, b));
        return ans;
    }
    void private_update(int nod, int i, int j, const int id, const int x)
    {
        if (i == j)
        {
            tree[nod] = x;
            return;
        }
        int m = (i + j) / 2;
        if (id <= m)
            private_update(nod * 2, i, m, id, x);
        else
            private_update(nod * 2 + 1, m + 1, j, id, x);
        tree[nod] = max(tree[nod * 2], tree[nod * 2 + 1]);
    }
};

bool fv[nmax];
int father[nmax];
int weight[nmax];
vector <int> vec[nmax];
vector <vector <int>> nodes;
vector <arbint> allTrees;

void dfs(int nod)
{
    fv[nod] = 1;
    int maxSon = 0;
    for (auto el: vec[nod])
        if (!fv[el])
        {
            father[el] = nod;
            dfs(el);
            weight[nod] += weight[el] + 1;
            if (maxSon == 0 || weight[maxSon] < weight[el])
                maxSon = el;
        }
    if (weight[nod] == 0)
    {
        nodes.push_back({nod});
        where[nod].first = nodes.size() - 1;
        where[nod].second = 1;
        return;
    }
    nodes[where[maxSon].first].push_back(nod);
    where[nod].first = where[maxSon].first;
    where[nod].second = where[maxSon].second + 1;
}

int merge(int nodX, int nodY)
{
    int ans = 0;
    while (where[nodX].first != where[nodY].first)
    {
        int first = allTrees[where[nodX].first].findMaxFromNode(nodX);
        int second = allTrees[where[nodY].first].findMaxFromNode(nodY);
        ans = max(ans, max(first, second));
        if (weight[nodX] > weight[nodY])
            swap(nodX, nodY);
        nodX = father[allTrees[where[nodX].first].last];
    }
    if (where[nodX].second > where[nodY].second)
        swap(nodX, nodY);
    int final = allTrees[where[nodX].first].findMax(where[nodX].second, where[nodY].second);
    return max(ans, final);
}

int main()
{
    int n, m;
    f >> n >> m;
    for (int i = 1; i <= n; ++ i)
        f >> v[i];
    for (int i = 1; i < n; ++ i)
    {
        int x, y;
        f >> x >> y;
        vec[x].push_back(y);
        vec[y].push_back(x);
    }
    father[1] = 1;
    dfs(1);
    for (auto el: nodes)
    {
        auto newTree(el);
        allTrees.push_back(newTree);
    }
    for (int i = 1; i <= m; ++ i)
    {
        int op, x, y;
        f >> op >> x >> y;
        if (op == 1)
            g << merge(x, y) << '\n';
        else
            allTrees[where[x].first].update(where[x].second, y);
    }
}