Cod sursa(job #3041418)

Utilizator lucametehauDart Monkey lucametehau Data 31 martie 2023 14:35:44
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.79 kb
#include <iostream>
#include <cmath>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <cstring>
#include <chrono>
#include <cassert>
#include <bitset>
#include <stack>
#include <queue>
#include <iomanip>
#include <random>
#include <string>
#include <complex>
#include <algorithm>
#include <numeric>
#include <immintrin.h>

#ifdef _MSC_VER
#  include <intrin.h>
#  define __builtin_popcount __popcnt
#  define __builtin_popcountll __popcnt64
#endif

#pragma warning(disable : 4996)

//#pragma GCC optimize("Ofast")
#define x first
#define y second
#define ld long double
#define ll long long
#define ull unsigned long long
#define us unsigned short
#define lsb(x) ((x) & (-(x)))
#define pii pair <int, int>
#define pll pair <ll, ll>

using namespace std;

//const int MOD = (int)1e9 + 7;

mt19937_64 gen(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count());
uniform_int_distribution <int> rng;
const ld PI = acos(-1);

const int MOD = (int)1e9 + 7;

class SegTree {
public:
    vector <int> tree;

    void init(int n) {
        tree.resize(4 * n + 5);
        fill(tree.begin(), tree.end(), 0);
    }

    void update(int node, int st, int dr, int ind, int val) {
        if (st == dr) {
            tree[node] = val;
            return;
        }
        int mid = (st + dr) >> 1;
        if (ind <= mid)
            update(2 * node, st, mid, ind, val);
        else
            update(2 * node + 1, mid + 1, dr, ind, val);
        tree[node] = max(tree[2 * node], tree[2 * node + 1]);
    }

    int query(int node, int st, int dr, int l, int r) {
        if (l <= st && dr <= r)
            return tree[node];
        int mid = (st + dr) >> 1;
        int ans = 0;

        if (l <= mid)
            ans = max(ans, query(2 * node, st, mid, l, r));
        if (mid < r)
            ans = max(ans, query(2 * node + 1, mid + 1, dr, l, r));
        return ans;
    }
};

class HLD {
public:
    vector <vector <int>> g;
    vector <int> top, ind, t, heavy_son, sz;
    SegTree tree;
    int timer;

    int N;

    void init(int n) {
        g.resize(n + 1);
        top.resize(n + 1);
        ind.resize(n + 1);
        sz.resize(n + 1);
        t.resize(n + 1);
        heavy_son.resize(n + 1);
        tree.init(n);
        N = n;

        timer = 0;
    }

    void init(int v[]) {
        for (int i = 1; i <= N; i++) {
            tree.update(1, 1, N, ind[i], v[i]);
        }
    }

    void add_egde(int x, int y) {
        g[x].push_back(y);
        g[y].push_back(x);
    }

    void dfs_init(int node, int par = 0) {
        sz[node] = 1;
        t[node] = par;
        top[node] = node;
        int mx = 0;
        for (auto& son : g[node]) {
            if (son == par)
                continue;
            dfs_init(son, node);
            sz[node] += sz[son];
            if (sz[son] > mx)
                mx = sz[son], heavy_son[node] = son;
        }
    }

    void dfs_build(int node, int par = 0) {
        top[node] = top[par];
        ind[node] = ++timer;
        if (heavy_son[node])
            dfs_build(heavy_son[node], par);

        for (auto& son : g[node]) {
            if (son == t[node] || son == heavy_son[node])
                continue;
            dfs_build(son, son);
        }
    }

    void update(int x, int y) {
        tree.update(1, 1, N, ind[x], y);
    }

    int query(int x, int y) {
        int ans = 0;
        while (top[x] != top[y]) {
            if (ind[x] < ind[y])
                swap(x, y);
            ans = max(ans, tree.query(1, 1, N, ind[top[x]], ind[x]));
            x = t[top[x]];
        }
        if (ind[x] < ind[y])
            swap(x, y);
        return max(ans, tree.query(1, 1, N, ind[y], ind[x]));
    }

} hld;

int v[100005];

void solve(int test = 0) {
    int n, q;
    cin >> n >> q;
    hld.init(n);
    for (int i = 1; i <= n; i++)
        cin >> v[i];

    for (int i = 1; i < n; i++) {
        int x, y;
        cin >> x >> y;
        hld.add_egde(x, y);
    }

    hld.dfs_init(1);
    hld.dfs_build(1, 1);
    hld.init(v);

    for (; q; q--) {
        int t, x, y;
        cin >> t >> x >> y;
        if (t == 0) {
            hld.update(x, y);
        }
        else {
            cout << hld.query(x, y) << "\n";
        }
    }
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    srand(time(0));

#ifdef LOCAL
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#else
    freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);
#endif

    int T = 1;

    //cin >> T;

    for (int t = 1; t <= T; t++) {
        solve(t);
    }

    return 0;
}