Cod sursa(job #2047070)

Utilizator mlc_oficialBoris Barca mlc_oficial Data 24 octombrie 2017 15:24:53
Problema Heavy Path Decomposition Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 3.67 kb
#pragma GCC optimize("Ofast")
#pragma GCC target("sse4")
#include <utility>
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

const int kMagic = 256;

class SqrtTree {
private:
    void dfs(int node) {
        for (auto&& son : G[node])
            if (parent[node] != son) {
                parent[son] = node;
                depth[son] = depth[node] + 1;
                dfs(son);
            }
    }

    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) {
                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);
        depth.resize(N);
        fill(parent.begin(), parent.end(), -1);
        dfs(0);
        
        super_parent.resize(N);
        fill(super_parent.begin(), super_parent.end(), -1);
        super_parent[0] = 0;
        for (int i = 1; i < N; ++i) {
            if (super_parent[i] != -1)
                continue;
            int iter = parent[i];
            while (depth[iter] % kMagic && super_parent[iter] == -1)
                iter = parent[iter];
            if (depth[iter] % kMagic)
                super_parent[i] = super_parent[iter];
            else
                super_parent[i] = super_parent[iter] = iter;
            for (int j = parent[i]; j != iter; j = parent[j])
                super_parent[j] = super_parent[i];
        }
        super_value = V;
        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] || super_parent[x] == -1)
                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';
        }
    }
}