Pagini recente » Cod sursa (job #90147) | Cod sursa (job #2293229) | Cod sursa (job #2019727) | Cod sursa (job #1199528) | Cod sursa (job #1510575)
#include <cstdio>
#include <algorithm>
#include <cctype>
using namespace std;
const int Nmax = 100000;
const int NIL = -1;
const int Bsize = 65536;
char buffer[Bsize];
int ptr = Bsize;
inline char GetChar() {
if (ptr == Bsize) {
fread(buffer, 1, Bsize, stdin);
ptr = 0;
}
return buffer[ptr++];
}
inline int ReadInt() {
int q = 0;
char c;
do {
c = GetChar();
} while (!isdigit(c));
do {
q = (10 * q) + (c - '0');
c = GetChar();
} while (isdigit(c));
return q;
}
struct Edge {
int v, next;
};
Edge l[2 * Nmax - 2]; // liste de adiacenta alocate static
int adj[Nmax]; // capete de liste
int key[Nmax]; // valorile date
int father[Nmax]; // father[u] = parintele nodului u
int depth[Nmax]; // depth[u] = adancimea nodului u
int siz[Nmax]; // siz[u] = marimea subarborelui cu radacina u
int path[Nmax]; // path[u] = cararea careia ii apartine u
int lenPath[Nmax]; // lenPath[i] = lungimea cararii i
int nPaths; // numarul total de carari
int posPath[Nmax]; // pozitia nodului u in cararea careia ii apartine
int startPath[Nmax]; // startPath[i] = nodul de start din cararea i
int **T; // arbori de intervale
void addEdge(int u, int v, int pos) {
l[pos].v = v;
l[pos].next = adj[u];
adj[u] = pos;
}
void dfs(int u) {
int heavySize = 0, i, v;
siz[u] = 1;
path[u] = NIL;
for (i = adj[u]; i != NIL; i = l[i].next) {
v = l[i].v;
if (father[v] == NIL) {
father[v] = u;
depth[v] = depth[u] + 1;
dfs(v);
siz[u] += siz[v];
if (heavySize < siz[v]) {
heavySize = siz[v];
path[u] = path[v];
}
}
}
if (path[u] == NIL) {
path[u] = nPaths++;
}
posPath[u] = lenPath[path[u]]++;
}
void buildHPD(int n) {
int i;
father[0] = 0;
depth[0] = 0;
dfs(0);
for (i = 0; i < n; i++) { // oglidim caile
posPath[i] = lenPath[path[i]] - posPath[i] - 1;
if (posPath[i] == 0) {
startPath[path[i]] = i;
}
}
}
void buildSegmentedTrees(int n) {
int i, j;
T = (int **) malloc(nPaths << 2);
for (i = 0; i < nPaths; i++) {
T[i] = (int *) malloc(lenPath[i] << 3);
}
for (i = 0; i < n; i++) {
T[path[i]][posPath[i] + lenPath[path[i]]] = key[i];
}
for (i = 0; i < nPaths; i++) {
for (j = lenPath[i] - 1; j > 0; j--) {
T[i][j] = max(T[i][j << 1], T[i][(j << 1) | 1]);
}
}
}
void update(int u, int key) {
int p = path[u];
int q = posPath[u] + lenPath[p], x;
T[p][q] = key;
while (q > 1) {
x = q >> 1;
T[p][x] = max(T[p][q], T[p][q ^ 1]);
q = x;
}
}
int segQuery(int path, int u, int v) {
int answer = 0;
if (u > v) {
swap(u, v);
}
u += lenPath[path];
v += lenPath[path] + 1;
while (u < v) {
if (u & 1) {
answer = max(answer, T[path][u]);
u++;
}
if (v & 1) {
v--;
answer = max(answer, T[path][v]);
}
u >>= 1;
v >>= 1;
}
return answer;
}
int query(int u, int v) {
if (depth[startPath[path[u]]] < depth[startPath[path[v]]]) {
swap(u, v);
}
if (path[u] == path[v]) {
return segQuery(path[u], posPath[u], posPath[v]);
} else { // u apartine caii celei mai adanci
return max(segQuery(path[u], 0, posPath[u]), query(father[startPath[path[u]]], v));
}
}
int main(void) {
freopen("heavypath.in", "r", stdin);
freopen("heavypath.out", "w", stdout);
int n, m, i;
int tip, u, v;
n = ReadInt(); m = ReadInt();
for (i = 0; i < n; i++) {
adj[i] = NIL;
father[i] = NIL;
key[i] = ReadInt();
}
for (i = 1; i < n; i++) {
u = ReadInt() - 1;
v = ReadInt() - 1;
addEdge(u, v, (i << 1) - 2);
addEdge(v, u, (i << 1) - 1);
}
buildHPD(n);
buildSegmentedTrees(n);
for (i = 0; i < m; i++) {
tip = ReadInt(); u = ReadInt(); v = ReadInt();
if (!tip) {
update(u - 1, v);
} else {
printf("%d\n", query(u - 1, v - 1));
}
}
fclose(stdin);
fclose(stdout);
return 0;
}