Mai intai trebuie sa te autentifici.
Cod sursa(job #2986768)
Utilizator | Data | 1 martie 2023 08:59:32 | |
---|---|---|---|
Problema | Heavy Path Decomposition | Scor | 20 |
Compilator | cpp-64 | Status | done |
Runda | Arhiva educationala | Marime | 3.86 kb |
#include <bits/stdc++.h>
#define NMAX 100000
using namespace std;
int n;
int v[NMAX + 1];
int vtata[NMAX + 1];
int vlevel[NMAX + 1];
int vdown[NMAX + 1];
vector <int> vsons[NMAX + 1];
int vtopchain[NMAX + 1];
int vindexaint[NMAX + 1];
int vorderaint[NMAX + 1];
int crtindex;
struct straint {
int vaint[4 * NMAX + 1];
void init() {
int i;
for (i = 0; i <= 4 * NMAX; i++)
vaint[i] = 0;
}
void build(int node, int left, int right) {
if (left == right) {
vaint[node] = v[vorderaint[left]];
return;
}
int med = (left + right) / 2;
build(node * 2, left, med);
build(node * 2 + 1, med + 1, right);
vaint[node] = max(vaint[node * 2], vaint[node * 2 + 1]);
}
void update(int node, int left, int right, int poz, int val) {
if (left == right) {
vaint[node] = val;
return;
}
int med = (left + right) / 2;
if (poz <= med)
update(node * 2, left, med, poz, val);
else
update(node * 2 + 1, med + 1, right, poz, val);
vaint[node] = max(vaint[node * 2], vaint[node * 2 + 1]);
}
int query(int node, int left, int right, int qleft, int qright) {
if (left == qleft && right == qright)
return vaint[node];
int med = (left + right) / 2;
if (qleft <= med && qright > med)
return max(query(node * 2, left, med, qleft, med), query(node * 2 + 1, med + 1, right, med + 1, qright));
else if (qleft <= med)
return query(node * 2, left, med, qleft, qright);
else
return query(node * 2 + 1, med + 1, right, qleft, qright);
}
};
straint AINT;
void dfs1(int node, int tata, int level) {
int i, nsons;
vtata[node] = tata;
vdown[node] = 1;
vlevel[node] = level;
nsons = vsons[node].size();
for (i = 0; i < nsons; i++) {
int newnode = vsons[node][i];
if (newnode != tata) {
dfs1(newnode, node, level + 1);
vdown[node] += vdown[newnode];
}
}
}
void dfs2(int node, int tata, int chainTop) {
int i, nsons, heavyIndex, maxDown;
vtopchain[node] = chainTop;
vindexaint[node] = crtindex;
vorderaint[crtindex] = node;
crtindex++;
maxDown = 0;
heavyIndex = -1;
nsons = vsons[node].size();
for (i = 0; i < nsons; i++) {
int newnode = vsons[node][i];
if (newnode != tata) {
if (vdown[node] > maxDown) {
heavyIndex = i;
maxDown = vdown[node];
}
}
}
if (heavyIndex != -1)
dfs2(vsons[node][heavyIndex], node, chainTop);
for (i = 0; i < nsons; i++) {
int newnode = vsons[node][i];
if (newnode != tata && i != heavyIndex)
dfs2(newnode, node, newnode);
}
}
int query(int node1, int node2) {
int sol = 0;
while (vtopchain[node1] != vtopchain[node2]) {
if (vlevel[vtopchain[node2]] > vlevel[vtopchain[node1]])
swap(node1, node2);
sol = max(sol, AINT.query(1, 0, n - 1, vindexaint[vtopchain[node1]], vindexaint[node1]));
node1 = vtata[vtopchain[node1]];
}
sol = max(sol, AINT.query(1, 0, n - 1, min(vindexaint[node1], vindexaint[node2]), max(vindexaint[node1], vindexaint[node2])));
return sol;
}
void update(int node, int val) {
AINT.update(1, 0, n - 1, vindexaint[node], val);
}
int main() {
FILE *fin, *fout;
fin = fopen("heavypath.in", "r");
fout = fopen("heavypath.out", "w");
int i, q, op, x, y;
fscanf(fin, "%d%d", &n, &q);
for (i = 1; i <= n; i++)
fscanf(fin, "%d", &v[i]);
for (i = 0; i < n - 1; i++) {
fscanf(fin, "%d%d", &x, &y);
vsons[x].push_back(y);
vsons[y].push_back(x);
}
dfs1(1, 0, 1);
crtindex = 0;
dfs2(1, 0, 1);
AINT.build(1, 0, n - 1);
while (q--) {
fscanf(fin, "%d%d%d", &op, &x, &y);
if (op == 0)
update(x, y);
else
fprintf(fout, "%d\n", query(x, y));
}
fclose( fin );
fclose( fout );
return 0;
}