Cod sursa(job #2575203)

Utilizator caesar2001Stoica Alexandru caesar2001 Data 6 martie 2020 12:04:39
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.75 kb
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <utility>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <cstdlib>
#define ll long long

using namespace std;

struct SegTree {
    vector<int> aint;

    void init(int n, const vector<int> &path, const vector<int> &v) {
        aint.resize(4 * n + 5, 0);
        buildtree(1, 1, n, v, path);
    }

    void buildtree(int node, int le, int ri, const vector<int> &v, const vector<int> &path) {
        if(le == ri)
            aint[node] = v[path[le]];
        else {
            int mid = (le + ri) / 2;
            buildtree(node * 2, le, mid, v, path);
            buildtree(node * 2 + 1, mid + 1, ri, v, path);
            aint[node] = max(aint[node * 2], aint[node * 2 + 1]);
        }
    }

    void update(int pos, int val, int node, int le, int ri) {
        if(le == ri)
            aint[node] = val;
        else {
            int mid = (le + ri) / 2;
            if(pos <= mid)
                update(pos, val, node * 2, le, mid);
            else
                update(pos, val, node * 2 + 1, mid + 1, ri);
            aint[node] = max(aint[node * 2], aint[node * 2 + 1]);
        }
    }

    int query(int from, int to, int node, int le, int ri) {
        if(from <= le && ri <= to)
            return aint[node];
        else {
            int mid = (le + ri) / 2;
            int ans = 0;
            if(from <= mid)
                ans = max(ans, query(from, to, node * 2, le, mid));
            if(mid < to)
                ans = max(ans, query(from, to, node * 2 + 1, mid + 1, ri));
            return ans;
        }
    }
};

struct HeavyPath {
    vector<vector<int>> g;
    int n, npaths;
    vector<int> whichpath, h, dim, father;
    vector<vector<int>> path;
    vector<int> pos, boss;
    vector<SegTree> aint;

    HeavyPath(int _n, vector<vector<int>> &_g, vector<int> &v) {
        n = _n;
        g = _g;
        npaths = 0;

        whichpath.resize(n + 1, 0);
        h.resize(n + 1, 0);
        dim.resize(n + 1, 0);
        father.resize(n + 1, 0);
        h[1] = 1;
        dfs(1, 0);

        pos.resize(n + 1, 0);
        boss.resize(npaths + 1, 0);
        path.resize(npaths + 1,  vector<int> (1, 0));
        computepaths(1, 0);
        exit(0);

        aint.resize(npaths + 1);
        for(int i = 1; i <= npaths; i ++)
            aint[i].init(path[i].size() - 1, path[i], v);

    }

    void dfs(int node, int dad) {
        father[node] = dad;
        dim[node] = 1;

        int mx = 0, from = 0;
        for(auto it : g[node]) {
            if(it == dad)
                continue;
            h[it] = h[node] + 1;
            dfs(it, node);
            dim[node] += dim[it];

            if(dim[it] > mx) {
                mx = dim[it];
                from = it;
            }
        }

        if(mx == 0) {
            npaths ++;
            whichpath[node] = npaths;
        } else {
            whichpath[node] = whichpath[from];
        }
    }

    int update(int node, int val) {
        aint[whichpath[node]].update(pos[node], val, 1, 1, path[whichpath[node]].size() - 1);
    }

    int query(int x, int y) {
        int ans = 0;
        while(whichpath[x] != whichpath[y]) {
            if(h[boss[whichpath[x]]] < h[boss[whichpath[y]]])
                swap(x, y);

            ans = max(ans, aint[whichpath[x]].query(pos[x], pos[boss[whichpath[x]]], 1, 1, path[whichpath[x]].size() - 1));
            x = father[boss[whichpath[x]]];
        }

        /// x si y sunt pe acelasi lant
        if(pos[x] > pos[y])
            swap(x, y);
        ans = max(ans, aint[whichpath[x]].query(pos[x], pos[y], 1, 1, path[whichpath[x]].size() - 1));
        return ans;
    }

    void computepaths(int node, int dad) {
        for(auto it : g[node]) {
            if(it == dad)
                continue;
            computepaths(it, node);
        }

        pos[node] = path[whichpath[node]].size();
        path[whichpath[node]].push_back(node);
        boss[whichpath[node]] = node;
    }
};


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

    int n, q;
    in >> n >> q;
    vector<int> v(n + 1, 0);
    for(int i = 1; i <= n; i ++)
        in >> v[i];
    vector<vector<int>> g(n + 1);
    for(int i = 1; i < n; i ++) {
        int x, y;
        in >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }

    HeavyPath ans(n, g, v);
    while(q --) {
        int t, x, y;
        in >> t >> x >> y;
        if(t == 0) {
            ans.update(x, y);
        } else if(t == 1) {
            out << ans.query(x, y) << "\n";
        }
    }

    return 0;
}