Cod sursa(job #2901086)

Utilizator Andrei-27Arhire Andrei Andrei-27 Data 12 mai 2022 21:41:12
Problema Heavy Path Decomposition Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.66 kb
#include <bits/stdc++.h>

using namespace std;

const long long NR = 1e5 + 1;
const int oo = 1e9;
int n, m, aIntCounter = -1;
vector<int> d, p, lvl, aIntPos, weight, aIntChain, parent;
vector<vector<int>> v, aInt, tree;


void updateSegTree(int chain, int nod, int st, int dr, int pos, int val) {
    if (st == dr) {
        tree[chain][nod] = val;
        return;
    }
    int mid = (st + dr) / 2;
    if (pos <= mid) {
        updateSegTree(chain, nod << 1, st, mid, pos, val);
    } else {
        updateSegTree(chain, nod << 1 | 1, mid + 1, dr, pos, val);
    }
    tree[chain][nod] = max(tree[chain][nod << 1], tree[chain][nod << 1 | 1]);
}

void buildSegTree() {
    for (int i = 0; i <= aIntCounter; ++i) {
        tree[i].resize((aInt[i].size() + 1) * 4 + 5, 0);
        for (int j = 0; j < aInt[i].size(); ++j) {
            updateSegTree(i, 1, 1, (int) aInt[i].size(), j + 1, d[aInt[i][j]]);
        }
    }
}

int querySegTree(int chain, int nod, int st, int dr, int a, int b) {
    if (a <= st && dr <= b) {
        return tree[chain][nod];
    }
    int mid = (st + dr) >> 1, leftMax = 0, rightMax = 0;
    if (a <= mid) {
        leftMax = querySegTree(chain, nod << 1, st, mid, a, b);
    }
    if (mid < b) {
        rightMax = querySegTree(chain, nod << 1 | 1, mid + 1, dr, a, b);
    }
    return max(leftMax, rightMax);
}

void dfs(int nod, int prt) {
    parent[nod] = prt;
    lvl[nod] = 1 + lvl[prt];
    weight[nod] = 1;
    int heaviest = -1, bestWeight = -1;
    for (auto it : v[nod]) {
        if (it == prt) {
            continue;
        }
        dfs(it, nod);
        weight[nod] += weight[it];
        if (weight[it] > bestWeight) {
            bestWeight = weight[it];
            heaviest = it;
        }
    }
    if (heaviest == -1) {
        ++aIntCounter;
        aInt[aIntCounter].emplace_back(nod);
        aIntPos[nod] = (int) aInt[aIntCounter].size() - 1;
        aIntChain[nod] = aIntCounter;
    } else {
        aInt[aIntChain[heaviest]].emplace_back(nod);
        aIntPos[nod] = (int) aInt[aIntChain[heaviest]].size() - 1;
        aIntChain[nod] = aIntChain[heaviest];
    }
}


int getMax(int chain, int st, int dr) {
    return querySegTree(chain, 1, 1, (int) aInt[chain].size(), st, dr);
}

int findMaximum(int x, int y) {
    int maximum = -oo;
    while (aIntChain[x] != aIntChain[y]) {
        if (lvl[parent[aInt[aIntChain[y]].back()]] > lvl[parent[aInt[aIntChain[x]].back()]]) {
            swap(x, y);
        }
        maximum = max(maximum, getMax(aIntChain[x], aIntPos[x] + 1, (int) aInt[aIntChain[x]].size()));
        x = parent[aInt[aIntChain[x]].back()];
    }
    return max(maximum, getMax(aIntChain[x], min(aIntPos[x], aIntPos[y]) + 1, max(aIntPos[x], aIntPos[y]) + 1));
}


signed main() {
    ifstream in("heavypath.in");
    ofstream out("heavypath.out");
    ios::sync_with_stdio(false);
    in.tie();
    int x, y, t;
    in >> n >> m;
    d.resize(n + 1, 0);
    parent.resize(n + 1, 0);
    p.resize(n + 1, 0);
    lvl.resize(n + 1, 0);
    aIntPos.resize(n + 1, 0);
    weight.resize(n + 1, 0);
    aIntChain.resize(n + 1, 0);
    v.resize(n + 1, vector<int>());
    aInt.resize(n + 1, vector<int>());
    tree.resize(n + 1, vector<int>());
    for (int i = 1; i <= n; ++i) {
        in >> d[i];
    }
    for (int i = 1; i < n; ++i) {
        in >> x >> y;
        v[x].emplace_back(y);
        v[y].emplace_back(x);
    }
    dfs(1, 0);
    buildSegTree();
    for (int i = 1; i <= m; ++i) {
        in >> t >> x >> y;
        if (t == 0) {
            updateSegTree(aIntChain[x], 1, 1, (int) aInt[aIntChain[x]].size(), aIntPos[x] + 1, y);
        } else {
            out << findMaximum(x, y) << '\n';
        }
    }
    in.close();
    out.close();
    return 0;
}