Pagini recente » Cod sursa (job #404548) | Cod sursa (job #2308531) | Cod sursa (job #254766) | Cod sursa (job #1052080) | Cod sursa (job #1223707)
#include <cstring>
#include <fstream>
#include <algorithm>
#include <vector>
using namespace std;
const int MAX_N = 100000;
const int MAX_P = 100000;
const int MAX_SIZE = 262144;
const int NIL = -1;
vector<int> T[MAX_N];
int V, Value[MAX_N], Father[MAX_N], Size[MAX_N], Level[MAX_N];
int PathCount, Paths[MAX_N], Begin[MAX_P], End[MAX_P], PathIndex[MAX_N], PathPosition[MAX_N];
int SegmentTree[MAX_SIZE], SegmentTreeSize;
inline void UpdateSegmentTree(int where, const int value) {
if (where < 0 || where >= SegmentTreeSize)
return;
SegmentTree[where += SegmentTreeSize] = value;
for (where /= 2; where > 0; where /= 2)
SegmentTree[where] = max(SegmentTree[2 * where], SegmentTree[2 * where + 1]);
}
inline int QuerySegmentTree(int from, int to) {
from = max(0, from);
to = min(SegmentTreeSize - 1, to);
if (from > to)
return 0;
from += SegmentTreeSize;
to += SegmentTreeSize;
int maxValue = 0;
while (from <= to) {
maxValue = max(maxValue, max(SegmentTree[from], SegmentTree[to]));
from = (from + 1) / 2;
to = (to - 1) / 2;
}
return maxValue;
}
void HeavyDFS(const int x) {
Size[x] = 1;
int heaviestSon = NIL;
for (const auto &y: T[x]) {
if (y == Father[x])
continue;
Father[y] = x;
Level[y] = Level[x] + 1;
HeavyDFS(y);
Size[x] += Size[y];
if (heaviestSon == NIL || Size[y] > Size[heaviestSon])
heaviestSon = y;
}
if (heaviestSon == NIL)
PathIndex[x] = PathCount++;
else
PathIndex[x] = PathIndex[heaviestSon];
++End[PathIndex[x]];
}
void PathDFS(const int x) {
for (const auto &y: T[x])
if (y != Father[x])
PathDFS(y);
Paths[End[PathIndex[x]]] = x;
PathPosition[x] = End[PathIndex[x]];
++End[PathIndex[x]];
}
void BuildSegmentTree() {
memset(SegmentTree, 0, sizeof(SegmentTree));
SegmentTreeSize = 1;
for (; SegmentTreeSize < End[PathCount - 1] + 1; SegmentTreeSize *= 2);
for (int where = 0; where < End[PathCount - 1] + 1; ++where)
SegmentTree[where + SegmentTreeSize] = Value[Paths[where]];
for (int where = SegmentTreeSize - 1; where > 0; --where)
SegmentTree[where] = max(SegmentTree[2 * where], SegmentTree[2 * where + 1]);
}
void BuildHeavyPathDecomposition() {
memset(Father, NIL, sizeof(Father));
memset(Level, -1, sizeof(Level));
memset(Size, 0, sizeof(Size));
memset(Begin, 0, sizeof(Begin));
memset(PathIndex, -1, sizeof(PathIndex));
memset(PathPosition, -1, sizeof(PathPosition));
Level[0] = 0;
HeavyDFS(0);
Begin[0] = 0;
End[0] = End[0] - 1;
for (int p = 1; p < PathCount; ++p) {
Begin[p] = End[p - 1] + 1;
End[p] = Begin[p] + End[p] - 1;
}
for (int p = 0; p < PathCount; ++p)
End[p] = Begin[p];
PathDFS(0);
for (int p = 0; p < PathCount; ++p)
--End[p];
BuildSegmentTree();
}
int Query(int x, int y) {
if (PathIndex[x] == PathIndex[y]) {
if (PathPosition[x] > PathPosition[y])
swap(x, y);
return QuerySegmentTree(PathPosition[x], PathPosition[y]);
}
if (Level[Paths[End[PathIndex[x]]]] < Level[Paths[End[PathIndex[y]]]])
swap(x, y);
return max(QuerySegmentTree(PathPosition[x], End[PathIndex[x]]), Query(Father[Paths[End[PathIndex[x]]]], y));
}
inline void AddEdge(const int x, const int y) {
T[x].push_back(y);
T[y].push_back(x);
}
int main() {
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
int Q;
cin >> V >> Q;
for (int x = 0; x < V; ++x)
cin >> Value[x];
for (int e = 1; e < V; ++e) {
int x, y;
cin >> x >> y;
AddEdge(x - 1, y - 1);
}
BuildHeavyPathDecomposition();
for (; Q > 0; --Q) {
int type;
cin >> type;
if (type == 0) {
int x, value;
cin >> x >> value;
Value[x - 1] = value;
UpdateSegmentTree(PathPosition[x - 1], value);
} else {
int x, y;
cin >> x >> y;
cout << Query(x - 1, y - 1) << "\n";
}
}
cin.close();
cout.close();
return 0;
}