Cod sursa(job #2522826)

Utilizator mihneacazCazacu Mihnea mihneacaz Data 13 ianuarie 2020 01:28:52
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.46 kb
#include <fstream>
#include <vector>
#include <cassert>
#include <cmath>

using namespace std;

const int NMAX = 100005;

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

int cost[NMAX], cul[NMAX], sub[NMAX], nivel[NMAX], f[NMAX], order[NMAX];
vector <int> g[NMAX];
vector < vector <int> > lant;
vector < vector <int> > tree;

void dfs(int node, int father, int lvl)
{
    sub[node] = 1;
    nivel[node] = lvl;
    f[node] = father;
    for(auto x: g[node]) {
        if(x != father) {
            dfs(x, node, lvl + 1);
            sub[node] += sub[x];
        }
    }
    if(sub[node] == 1) {
        lant.push_back({node});
        cul[node] = lant.size() - 1;
    } else {
        int maxim_size = 0;
        for(auto x: g[node]) {
            if(x == father)
                continue;
            if(sub[x] > sub[maxim_size]) {
                maxim_size = x;
            }
        }
        lant[cul[maxim_size]].push_back(node);
        cul[node] = cul[maxim_size];
    }
}

void update_tree(vector <int> &currTree, int node, int st, int dr, int target, int val)
{
    if(st == dr) {
        currTree[node] = val;
        return;
    }
    int med = (st + dr) / 2;
    if(target <= med)
        update_tree(currTree, node * 2, st, med, target, val);
    else
        update_tree(currTree, node * 2 + 1, med + 1, dr, target, val);
    currTree[node] = max(currTree[node * 2], currTree[node * 2 + 1]);
}

int query_tree(vector <int> &currTree, int node, int st, int dr, int left, int right)
{
    int maxim = 0;
    if(left <= st && dr <= right)
        return currTree[node];
    int med = (st + dr) / 2;
    if(left <= med)
        maxim = max(maxim, query_tree(currTree, node * 2, st, med, left, right));
    if(right > med)
        maxim = max(maxim, query_tree(currTree, node * 2 + 1, med + 1, dr, left, right));
    return maxim;
}

int query(int x, int y)
{
    int maxim = 0;
    while(cul[x] != cul[y]) {
        if(nivel[f[lant[cul[x]].back()]] > nivel[f[lant[cul[y]].back()]]) {
            maxim = max(maxim, query_tree(tree[cul[x]], 1, 1, lant[cul[x]].size(), order[x], order[lant[cul[x]].back()]));
            x = f[lant[cul[x]].back()];
        } else {
            maxim = max(maxim, query_tree(tree[cul[y]], 1, 1, lant[cul[y]].size(), order[y], order[lant[cul[y]].back()]));
            y = f[lant[cul[y]].back()];
        }
    }
    maxim = max(maxim, query_tree(tree[cul[x]], 1, 1, lant[cul[x]].size(), min(order[x], order[y]), max(order[x], order[y])));
    return maxim;
}

int main() {
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= n; ++i) {
        cin >> cost[i];
    }
    for(int i = 1; i <= n - 1; ++i) {
        int x, y;
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    dfs(1, -1, 1);
    tree.resize(lant.size());
    for(int i = 0; i < lant.size(); ++i) {
        assert(lant[i].size() > 0);
        tree[i].resize(lant[i].size() * 4);
        for(int j = 0; j < lant[i].size(); ++j)
            order[lant[i][j]] = j + 1;
    }
    for(int i = 1; i <= n; ++i) {
        update_tree(tree[cul[i]], 1, 1, lant[cul[i]].size(), order[i], cost[i]);
    }
    for(int i = 1; i <= m; ++i) {
        int task;
        cin >> task;
        if(task == 0) {
            int node, val;
            cin >> node >> val;
            update_tree(tree[cul[node]], 1, 1, lant[cul[node]].size(), order[node], val);
        } else {
            int x, y;
            cin >> x >> y;
            cout << query(x, y) << "\n";
        }
    }
    return 0;
}