Cod sursa(job #2047101)

Utilizator mlc_oficialBoris Barca mlc_oficial Data 24 octombrie 2017 16:05:22
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.75 kb
#include <cassert>
#include <utility>
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

static const int kMagic = 256;

class SqrtTree {
private:
    void dfs_push(int node, int group) {
        for (auto&& son : G[node])
            if (parent[node] != son && super_parent[son] == group) {
                super_value[son] = max(V[son], super_value[node]);
                dfs_push(son, group);
            }
    }

    void dfs_value(int node) {
        for (auto&& son : G[node])
            if (parent[node] != son) {
                depth[son] = depth[node] + 1;
                if (super_parent[son] == super_parent[node])
                    super_value[son] = max(super_value[node], super_value[son]);
                dfs_value(son);
            }
    }

    void initialize() {
        parent.resize(N);
        fill(parent.begin(), parent.end(), -1);
        
        vector<int> S;
        vector<int> preorder;
        S.push_back(0);
        parent[0] = 0;
        while (!S.empty()) {
            int node = S.back();
            S.pop_back();
            preorder.push_back(node);
            for (auto&& son : G[node])
                if (parent[node] != son) {
                    parent[son] = node;
                    S.push_back(son);
                }
        }
          
        super_parent.resize(N);
        fill(super_parent.begin(), super_parent.end(), -1);
        depth.resize(N);
        for (int i = N - 1; i > 0; --i) {
            int node = preorder[i];
            if (++depth[node] == kMagic) {
                super_parent[node] = node;
                depth[node] = 0;
            }
            depth[parent[node]] = max(depth[parent[node]], depth[node]);
        }

        super_parent[0] = 0;
        for (auto&& x : preorder)
            if (super_parent[x] == -1)
                super_parent[x] = super_parent[parent[x]];

        super_value = V;
        depth[0] = 0;
        dfs_value(0);
    }
public:
    SqrtTree() = default;
    SqrtTree(vector<int>& _V, vector< vector<int> >& _G) : V(move(_V)), G(move(_G)), N((int)V.size()) {
        initialize();
    }

    int query(int x, int y) {
        int ans = 0;
        while (super_parent[x] != super_parent[y]) {
            if (depth[x] < depth[y])
                swap(x, y);
            ans = max(ans, super_value[x]);
            x = parent[super_parent[x]];
        }
        while (x != y) {
            if (depth[x] < depth[y])
                swap(x, y);
            ans = max(ans, V[x]);
            x = parent[x];
        }
        ans = max(ans, V[x]);
        return ans;
    }
    
    void set_value(int node, const int& new_value) {
        V[node] = new_value;
        super_value[node] = new_value;
        if (parent[node] != -1 && super_parent[parent[node]] == super_parent[node])
            super_value[node] = max(super_value[node], super_value[parent[node]]);
        dfs_push(node, super_parent[node]);
    }

    vector<int> V;
    vector< vector<int> > G;
    vector<int> parent, super_parent, super_value;
    vector<int> depth;
    int N;
};

int main() {
#ifdef LOCAL
    ifstream cin("a.in");
#else
    ifstream cin("heavypath.in");
    ofstream cout("heavypath.out");
#endif

    int N, Q; cin >> N >> Q;
    vector<int> V(N);
    for (int i = 0; i < N; ++i)
        cin >> V[i];
    
    vector<vector<int> > G(N);
    for (int i = 1; i < N; ++i) {
        int x, y; cin >> x >> y; x--; y--;
        G[x].push_back(y);
        G[y].push_back(x);
    }

    SqrtTree tree(V, G);
    while (Q--) {
        int type; cin >> type;
        if (type == 0) {
            int node, value; cin >> node >> value; node--;
            tree.set_value(node, value);
        } else {
            int x, y; cin >> x >> y; x--; y--;
            cout << tree.query(x, y) << '\n';
        }
    }
}