Cod sursa(job #3233303)

Utilizator MirceaDonciuLicentaLicenta Mircea Donciu MirceaDonciuLicenta Data 2 iunie 2024 22:47:22
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.65 kb
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <limits>

using namespace std;

const int MAXN = 100000;
const int INF = numeric_limits<int>::max();

vector<int> tree[MAXN];
int parent[MAXN], depth[MAXN], heavy[MAXN], head[MAXN], pos[MAXN];
int value[MAXN];
int current_pos;
int segtree[4 * MAXN];
int N, M;

void dfs(int v) {
    int size = 1;
    int max_subtree_size = 0;

    for (int u : tree[v]) {
        if (u != parent[v]) {
            parent[u] = v;
            depth[u] = depth[v] + 1;
            int subtree_size = dfs(u);
            size += subtree_size;

            if (subtree_size > max_subtree_size) {
                max_subtree_size = subtree_size;
                heavy[v] = u;
            }
        }
    }

    return size;
}

void decompose(int v, int h) {
    head[v] = h;
    pos[v] = current_pos++;

    if (heavy[v] != -1) {
        decompose(heavy[v], h);
    }

    for (int u : tree[v]) {
        if (u != parent[v] && u != heavy[v]) {
            decompose(u, u);
        }
    }
}

void buildSegTree(int node, int start, int end) {
    if (start == end) {
        segtree[node] = value[start];
    } else {
        int mid = (start + end) / 2;
        buildSegTree(2 * node, start, mid);
        buildSegTree(2 * node + 1, mid + 1, end);
        segtree[node] = max(segtree[2 * node], segtree[2 * node + 1]);
    }
}

void updateSegTree(int node, int start, int end, int idx, int val) {
    if (start == end) {
        segtree[node] = val;
    } else {
        int mid = (start + end) / 2;
        if (start <= idx && idx <= mid) {
            updateSegTree(2 * node, start, mid, idx, val);
        } else {
            updateSegTree(2 * node + 1, mid + 1, end, idx, val);
        }
        segtree[node] = max(segtree[2 * node], segtree[2 * node + 1]);
    }
}

int querySegTree(int node, int start, int end, int l, int r) {
    if (r < start || end < l) {
        return -INF;
    }
    if (l <= start && end <= r) {
        return segtree[node];
    }
    int mid = (start + end) / 2;
    int p1 = querySegTree(2 * node, start, mid, l, r);
    int p2 = querySegTree(2 * node + 1, mid + 1, end, l, r);
    return max(p1, p2);
}

int query(int a, int b) {
    int res = -INF;
    while (head[a] != head[b]) {
        if (depth[head[a]] > depth[head[b]]) {
            swap(a, b);
        }
        res = max(res, querySegTree(1, 0, N - 1, pos[head[b]], pos[b]));
        b = parent[head[b]];
    }
    if (depth[a] > depth[b]) {
        swap(a, b);
    }
    res = max(res, querySegTree(1, 0, N - 1, pos[a], pos[b]));
    return res;
}

void update(int idx, int val) {
    updateSegTree(1, 0, N - 1, pos[idx], val);
}

int main() {
    ifstream infile("heavypath.in");
    ofstream outfile("heavypath.out");

    infile >> N >> M;
    for (int i = 0; i < N; ++i) {
        infile >> value[i];
    }

    for (int i = 0; i < N - 1; ++i) {
        int a, b;
        infile >> a >> b;
        --a; --b;
        tree[a].push_back(b);
        tree[b].push_back(a);
    }

    memset(heavy, -1, sizeof(heavy));
    parent[0] = -1;
    depth[0] = 0;
    current_pos = 0;

    dfs(0);
    decompose(0, 0);
    buildSegTree(1, 0, N - 1);

    for (int i = 0; i < M; ++i) {
        int t, x, y;
        infile >> t >> x >> y;
        --x; // Convert to 0-based index
        if (t == 0) {
            update(x, y);
        } else {
            --y; // Convert to 0-based index
            outfile << query(x, y) << endl;
        }
    }

    infile.close();
    outfile.close();

    return 0;
}