Cod sursa(job #2046701)

Utilizator retrogradLucian Bicsi retrograd Data 24 octombrie 2017 00:23:11
Problema Heavy Path Decomposition Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 2.58 kb
#include <bits/stdc++.h>

using namespace std;

using arr = int[500000];
arr Agg, Depth, Parent, Link, Value, Jump, Enter;
vector<int> G[500000];
const int kMagic = 512;

int timer;

void DFS(int node, int par, int depth) {
    Parent[node] = par;
    Jump[node] = (depth % kMagic == 0 ? node : Jump[par]);
    Enter[node] = timer++;
    Depth[node] = depth;
    for (auto vec : G[node]) {
        if (vec != par)
            DFS(vec, node, depth + 1);
    }
}   

int GetLCA(int a, int b) {
    while (a != b) {
        if (Depth[a] < Depth[b]) swap(a, b);
        if (a != Jump[a] && Depth[Jump[a]] >= Depth[b]) a = Jump[a];
        else a = Parent[a];
    }
    return a;    
}


vector<int> CompressTree(vector<int> v, arr ret) {
    auto cmp = [&](int a, int b) { 
        return Enter[a] < Enter[b]; 
    };
    sort(v.begin(), v.end(), cmp);
    v.erase(unique(v.begin(), v.end()), v.end());

    for (int i = (int)v.size() - 1; i > 0; --i)
        v.push_back(GetLCA(v[i - 1], v[i]));
    
    sort(v.begin(), v.end(), cmp);
    v.erase(unique(v.begin(), v.end()), v.end());
    
    for (int i = 0; i < (int)v.size(); ++i) 
        ret[v[i]] = (i == 0 ? -1 : GetLCA(v[i - 1], v[i]));
    return v;
}

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

    int n, m; cin >> n >> m;
    for (int i = 0; i < n; ++i) {
        cin >> Value[i];
    }

    for (int i = 1; i < n; ++i) {
        int a, b; cin >> a >> b;
        G[a - 1].push_back(b - 1);
        G[b - 1].push_back(a - 1);
    }

    DFS(0, -1, 0);

    for (int i = 0; i < m; i += kMagic) {
        vector<tuple<int, int, int>> qs;
        
        vector<int> sub;
        for (int j = i; j < m && j < i + kMagic; ++j) {
            int t, a, b; cin >> t >> a >> b;
            sub.push_back(--a); if (t == 1) sub.push_back(--b);
            qs.emplace_back(t, a, b);
        }


        sub = CompressTree(sub, Link);

        for (auto& node : sub) {
            Agg[node] = 0; int anc = Link[node];
            for (node = Parent[node]; node != anc; node = Parent[node])
                Agg[node] = max(Agg[node], Value[node]);
        }

        for (auto q : qs) {
            int t, a, b; tie(t, a, b) = q;
            if (t == 0) Value[a] = b;
            else {
                int res = 0;
                while (a != b) {
                    if (Depth[a] < Depth[b]) swap(a, b);
                    res = max(res, Value[a]);
                    res = max(res, Agg[a]);
                    a = Link[a]; 
                }
                cout << max(res, Value[a]) << '\n';
            }
        }

    } 
    
    return 0;
}