Pagini recente » Cod sursa (job #1759143) | Cod sursa (job #516812) | Cod sursa (job #300907) | Cod sursa (job #1197961) | Cod sursa (job #986715)
Cod sursa(job #986715)
#include <fstream>
#include <algorithm>
#include <vector>
using namespace std;
const int NIL = -1;
template<class IntType>
class SegmentTree {
public:
SegmentTree(const vector<IntType> &values) {
for (size = 1; size < int(values.size()); size *= 2);
tree = vector<IntType>(2 * size + 1, 0);
for (int x = 0; x < int(values.size()); ++x)
tree[size + x] = values[x];
for (int x = size - 1; x > 0; --x)
tree[x] = max(tree[2 * x], tree[2 * x + 1]);
}
void SetValue(int where, const IntType value) {
tree[where += size] = value;
for (where /= 2; where > 0; where /= 2)
tree[where] = max(tree[2 * where], tree[2 * where + 1]);
}
IntType QueryMax(int from, int to) const {
IntType answer = 0;
from += size;
to += size;
while (from <= to) {
answer = max(answer, max(tree[from], tree[to]));
from = (from + 1) / 2;
to = (to - 1) / 2;
}
return answer;
}
private:
int size;
vector<IntType> tree;
};
vector< vector<int> > Tree;
int V, Q;
vector<int> Values, Father, Level, Size, PathIndex, Position, Begin;
vector< vector<int> > Paths;
vector< SegmentTree<int> > SegmentTrees;
void DFS(const int x) {
Size[x] = 1;
int heaviestSon = NIL;
for (const auto &y: Tree[x]) {
if (Father[y] == NIL) {
Father[y] = x;
Level[y] = Level[x] + 1;
DFS(y);
Size[x] += Size[y];
if (heaviestSon == NIL || Size[heaviestSon] < Size[y])
heaviestSon = y;
}
}
if (heaviestSon == NIL) {
Paths.push_back(vector<int>());
PathIndex[x] = int(Paths.size()) - 1;
} else {
PathIndex[x] = PathIndex[heaviestSon];
}
Paths[PathIndex[x]].push_back(x);
}
void BuildHeavyPathDecomposition() {
for (auto &f: Father)
f = NIL;
Father[0] = 0;
Level[0] = 0;
DFS(0);
Begin = vector<int>(int(Paths.size()), NIL);
for (int p = 0; p < int(Paths.size()); ++p) {
reverse(Paths[p].begin(), Paths[p].end());
for (int i = 0; i < int(Paths[p].size()); ++i)
Position[Paths[p][i]] = i;
Begin[p] = Paths[p][0];
}
}
void BuildSegmentTrees() {
for (const auto &path: Paths) {
vector<int> pathValues(int(path.size()));
for (int i = 0; i < int(path.size()); ++i)
pathValues[i] = Values[path[i]];
SegmentTrees.push_back(SegmentTree<int>(pathValues));
}
}
int QueryPath(int x, int y) {
if (Level[Begin[PathIndex[x]]] < Level[Begin[PathIndex[y]]])
swap(x, y);
if (PathIndex[x] == PathIndex[y])
return SegmentTrees[PathIndex[x]].QueryMax(min(Position[x], Position[y]), max(Position[x], Position[y]));
return max(SegmentTrees[PathIndex[x]].QueryMax(0, Position[x]), QueryPath(Father[Begin[PathIndex[x]]], y));
}
void Solve(ifstream &cin, ofstream &cout) {
BuildHeavyPathDecomposition();
BuildSegmentTrees();
for (; Q > 0; --Q) {
int type, x, y;
cin >> type >> x >> y;
if (type == 0) {
--x;
Values[x] = y;
SegmentTrees[PathIndex[x]].SetValue(Position[x], y);
} else {
--x;
--y;
cout << QueryPath(x, y) << "\n";
}
}
}
void ReadTree(ifstream &cin) {
cin >> V >> Q;
Tree = vector< vector<int> >(V, vector<int>());
Values = Father = Level = Size = PathIndex = Position = vector<int>(V, 0);
for (int x = 0; x < V; ++x)
cin >> Values[x];
for (int i = 1; i < V; ++i) {
int x, y;
cin >> x >> y;
--x;
--y;
Tree[x].push_back(y);
Tree[y].push_back(x);
}
}
int main() {
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
ReadTree(cin);
Solve(cin, cout);
cin.close();
cout.close();
return 0;
}