Pagini recente » Cod sursa (job #570011) | Cod sursa (job #490595) | Cod sursa (job #104133) | Cod sursa (job #2698010) | Cod sursa (job #2986760)
#include <fstream>
#include <vector>
using namespace std;
const int N = 1e5 + 7;
namespace LI {
int ant[N], ult[N], v[N];
int timp;
void add(int a, int b) {
ant[++timp] = ult[a];
ult[a] = timp;
v[timp] = b;
}
}
namespace AINT { ///maxim pe interval, update pe nod
int t[2 * N];
int n;
void SetN(int _n) {
n = _n;
}
void UpdatePreBuild(int p, int v) {
t[p + n] = v;
}
void Build() {
for (int p = n - 1; p; --p)
t[p] = max(t[p << 1], t[p << 1 | 1]);
}
void Update(int p, int v) {
p--;
for (t[p += n] = v; p > 1; p >>= 1)
t[p >> 1] = max(t[p], t[p ^ 1]);
}
int Query(int l, int r) {///[l, r) indexat de la 0
++r;
int a(0);
for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
if (l & 1)
a = max(a, t[l++]);
if (r & 1)
a = max(a, t[--r]);
}
return a;
}
int Query(const vector < pair < int, int > > &intervale) {
int a(0);
for (auto i : intervale)
a = max(a, Query(i.first, i.second));
return a;
}
}
namespace HLD {
int head[N], p[N], g[N], h[N], t[N];
int timp;
void dfsG(int u) {
g[u] = 1;
for (int i = LI::ult[u]; i; i = LI::ant[i]) {
int v = LI::v[i];
if (v == t[u])
continue;
h[v] = 1 + h[u];
t[v] = u;
dfsG(v);
g[u] += g[v];
}
}
void dfsHLD(int u) {
int heavyW(0);
for (int i = LI::ult[u]; i; i = LI::ant[i]) {
int v = LI::v[i];
if (v == t[u])
continue;
if (heavyW == 0 || g[heavyW] < g[v])
heavyW = v;
}
if (!heavyW)
return;
head[heavyW] = head[u];
p[heavyW] = ++timp;
dfsHLD(heavyW);
for (int i = LI::ult[u]; i; i = LI::ant[i]) {
int v = LI::v[i];
if (v == t[u] || head[v])
continue;
head[v] = v;
p[v] = ++timp;
dfsHLD(v);
}
}
void Build() {
dfsG(1);
head[1] = 1;
dfsHLD(1);
}
vector < pair < int, int > > GetIntervals(int u, int v) {
vector < pair < int, int > > a;
while (head[u] != head[v]) {
if (h[head[u]] < h[head[v]])
swap(u, v);
a.push_back({p[head[u]], p[u]});
u = t[head[u]];
}
a.push_back({min(p[u], p[v]), max(p[u], p[v])});
return a;
}
}
int v[N];
int main()
{
///m-am gandit sa fac o parcurgere dfs sa renotez nodurile sa fie calculele mai cache friendly, dar am doar doua dfs-uri si sa fac trei sa fie doua mai cache friendly nu merita
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int n, q;
fin >> n >> q;
AINT::SetN(n);
for (int i = 1; i <= n; ++i)
fin >> v[i];
for (int i = 1; i < n; ++i) {
int u, v;
fin >> u >> v;
LI::add(u, v);
LI::add(v, u);
}
HLD::Build();
for (int i = 1; i <= n; ++i)
AINT::UpdatePreBuild(HLD::p[i], v[i]);
AINT::Build();
while (q--) {
int t, a, b;
fin >> t >> a >> b;
if (t)
fout << AINT::Query(HLD::GetIntervals(a, b)) << '\n';
else
AINT::Update(a, b);
}
return 0;
}