Cod sursa(job #3263151)

Utilizator not_anduAndu Scheusan not_andu Data 13 decembrie 2024 18:13:52
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.26 kb
/*
! Abordarea Heavy Path
*/

#include <bits/stdc++.h>

using namespace std;

#define INFILE "heavypath.in"
#define OUTFILE "heavypath.out"

struct AINT {

private:
    int n;
    vector<int> aint;

public:
    AINT(){}
    AINT(int _n) : n(_n) {
        aint.resize(2 * n + 1, 0);
    }

    void update(int position, int value){
        for(aint[position += n - 1] = value; position > 1; position >>= 1){
            aint[position >> 1] = max(aint[position], aint[position ^ 1]);
        }
    }

    int query(int queryLeft, int queryRight){
        int ans = 0;
        for(queryLeft += n - 1, queryRight += n; queryLeft < queryRight; queryLeft >>= 1, queryRight >>= 1){
            if(queryLeft & 1) ans = max(ans, aint[queryLeft++]);
            if(queryRight & 1) ans = max(ans, aint[--queryRight]);
        }
        return ans;
    }

};

const int N_MAX = 1e5;
const int M_MAX = 1e5;

int nodes, queries;

int a[N_MAX + 5];
int sz[N_MAX + 5];
int level[N_MAX + 5];
int parent[N_MAX + 5];
int heavySon[N_MAX + 5];

int paths;
int timer;
int tin[N_MAX + 5];
int head[N_MAX + 5];
int label[N_MAX + 5];

vector<int> adj[N_MAX + 5];

AINT aint;

void dfs(int node){
    level[node] = level[parent[node]] + 1;
    sz[node] = 1;
    heavySon[node] = 0;
    for(auto &to : adj[node]){
        if(to != parent[node]){
            parent[to] = node;
            dfs(to);
            sz[node] += sz[to];
            if(sz[to] > sz[heavySon[node]]){
                heavySon[node] = to;
            }
        }
    }
}

void decomposition(int node){
    tin[node] = ++timer;
    if(heavySon[node] != 0){
        decomposition(heavySon[node]);
        label[node] = label[heavySon[node]];
    }
    else {
        label[node] = ++paths;
    }
    head[label[node]] = node;
    for(auto &to : adj[node]){
        if(to != parent[node] && to != heavySon[node]){
            decomposition(to);
        }
    }
}

int maxPath(int node1, int node2){
    int ans = 0;
    while(label[node1] != label[node2]){
        if(level[head[label[node1]]] > level[head[label[node2]]]){
            ans = max(ans, aint.query(tin[node1], tin[head[label[node1]]]));
            node1 = parent[head[label[node1]]];
        }
        else {
            ans = max(ans, aint.query(tin[node2], tin[head[label[node2]]]));
            node2 = parent[head[label[node2]]];
        }
    }
    if(tin[node1] > tin[node2]) swap(node1, node2);

    ans = max(ans, aint.query(tin[node1], tin[node2]));
    return ans;
}

void solve(){

    cin >> nodes >> queries;

    for(int i = 1; i <= nodes; ++i){
        cin >> a[i];
    }

    for(int i = 1; i < nodes; ++i){
        int node1, node2; cin >> node1 >> node2;
        adj[node1].push_back(node2);
        adj[node2].push_back(node1);
    }

    dfs(1);
    decomposition(1);

    aint = nodes;
    for(int i = 1; i <= nodes; ++i){
        tin[i] = nodes - tin[i] + 1;
        aint.update(tin[i], a[i]);
    }

    for(int i = 0; i < queries; ++i){
        int type, x, y; cin >> type >> x >> y;
        if(type == 0){
            aint.update(tin[x], y);
        }   
        else {
            cout << maxPath(x, y) << '\n';
        }
    }

}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    freopen(INFILE, "r", stdin);
    freopen(OUTFILE, "w", stdout);
    solve();
    return 0;
}