Pagini recente » Cod sursa (job #267619) | Cod sursa (job #3282538) | Cod sursa (job #1604855) | Cod sursa (job #2044149)
#include <bits/stdc++.h>
using namespace std;
int combine(int x, int y){
return max(x, y);
}
class SegmentTree{
private:
vector<int> tree;
int N;
void build(const vector<int> &that){
for (int i = 0; i < N; i++){
tree[i + N] = that[i];
}
for (int i = N - 1; i > 0; i--)
tree[i] = combine(tree[2 * i], tree[2 * i + 1]);
}
public:
SegmentTree(const vector<int> &that){
N = (int)that.size();
tree.resize(2 * N);
build(that);
}
void update(int pos, int key){
pos += N;
tree[pos] = key;
while (pos > 1){
tree[pos / 2] = combine(tree[pos], tree[pos ^ 1]);
pos /= 2;
}
}
int query(int l, int r) const{
l += N; r += N;
r++;
int result = numeric_limits<int>::min() / 2;
while (l < r){
if (l & 1){
result = max(result, tree[l]);
l++;
}
if (r & 1){
r--;
result = max(result, tree[r]);
}
l /= 2;
r /= 2;
}
return result;
}
};
constexpr int MAX = 100000;
using Graph = vector<vector<int>>;
template<size_t MAX>
using Array = array<int, MAX>;
Graph graph;
Array<MAX> father, depth, size_subtree;
Array<MAX> length_path, pos_in_path, path, start_node;
vector<SegmentTree> segtrees;
vector<int> keys;
int num_paths;
void dfs(int node){
int heavy_son = -1;
size_subtree[node] = 1;
for (int v: graph[node]){
if (father[v] == -1){
father[v] = node;
depth[v] = depth[node] + 1;
dfs(v);
size_subtree[node] += size_subtree[v];
if (heavy_son == -1 || size_subtree[heavy_son] < size_subtree[v])
heavy_son = v;
}
}
if (heavy_son == -1)
path[node] = ::num_paths++;
else
path[node] = path[heavy_son];
pos_in_path[node] = length_path[path[node]]++;
}
void build_heavy_paths(int N){
fill(father.begin(), father.begin() + N, -1);
father[0] = 0;
dfs(0);
for (int i = 0; i < N; i++){
pos_in_path[i] = length_path[path[i]] - pos_in_path[i] - 1;
if (pos_in_path[i] == 0)
start_node[path[i]] = i;
}
vector<vector<int>> all_keys(num_paths);
for (int i = 0; i < ::num_paths; i++)
all_keys[i].resize(length_path[i]);
for (int i = 0; i < N; i++)
all_keys[path[i]][pos_in_path[i]] = keys[i];
for (int i = 0; i < ::num_paths; i++)
segtrees.push_back(SegmentTree(all_keys[i]));
}
void update(int node, int new_key){
segtrees[path[node]].update(pos_in_path[node], new_key);
}
int query(int x, int y){
if (depth[start_node[path[x]]] < depth[start_node[path[y]]])
swap(x, y);
if (path[x] == path[y])
return segtrees[path[x]].query(min(pos_in_path[x], pos_in_path[y]),
max(pos_in_path[x], pos_in_path[y]));
else return combine(segtrees[path[x]].query(0, pos_in_path[x]),
query(father[start_node[path[x]]], y));
}
int main(){
ios_base::sync_with_stdio(false);
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
int N, Q;
cin >> N >> Q;
keys.resize(N);
for (int &x: keys)
cin >> x;
graph.resize(N);
for (int i = 0; i < N - 1; i++){
int u, v;
cin >> u >> v;
u--; v--;
graph[u].push_back(v);
graph[v].push_back(u);
}
build_heavy_paths(N);
while (Q--){
int t;
cin >> t;
if (t == 0){
int x, k;
cin >> x >> k;
x--;
update(x, k);
}
else{
int x, y;
cin >> x >> y;
x--; y--;
cout << query(x, y) << "\n";
}
}
return 0;
}