Pagini recente » Istoria paginii utilizator/sygandreiionita | Cod sursa (job #1762826) | Cod sursa (job #384567) | Mall | Cod sursa (job #2417259)
#include <algorithm>
#include <iostream>
#include <memory.h>
#include <fstream>
#include <cassert>
#include <vector>
#include <array>
using namespace std;
ifstream in("heavypath.in");
ofstream out("heavypath.out");
const int NMAX = 1e5;
int n, m, nrc;
int levelg[1 + NMAX];
int parent[1 + NMAX];
int cno[1 + NMAX];
int cpos[1 + NMAX];
int ni[1 + NMAX];
int ssz[1 + NMAX];
int v[1 + NMAX];
vector < int > g[1 + NMAX];
vector < int > chain[1 + NMAX];
vector < int > aint[1 + NMAX];
void dfs(int node, int p) {
vector < int > :: iterator to;
levelg[node] = levelg[p] + 1;
ssz[node] = 1;
if(g[node].size() == 1) {
nrc++;
chain[nrc].push_back(node);
cno[node] = nrc;
//cpos[node] = chain[nrc].size() - 1;
return;
}
int sszm = -1;
int chn;
for(to = g[node].begin(); to != g[node].end(); to++) {
if(*to == p)
continue;
dfs(*to, node);
ssz[node] += ssz[*to];
parent[*to] = node;
if(sszm < ssz[*to]) {
sszm = ssz[*to];
chn = cno[*to];
}
}
assert(0 <= sszm);
chain[chn].push_back(node);
cno[node] = chn;
//cpos[node] = chain[chn].size() - 1;
}
void update(int nr, int i) {
if(0 < i) {
aint[nr][i] = aint[nr][2 * i];
if(v[aint[nr][i]] < v[aint[nr][2 * i + 1]])
aint[nr][i] = aint[nr][2 * i + 1];
update(nr, i / 2);
}
}
void makeaint(int nr) {
int exp = 0;
int sz = chain[nr].size();
for(int i = 0; i <= 5 * sz + 10; i++)
aint[nr].push_back(0);
while((1 << exp) < sz)
exp++;
ni[nr] = (1 << exp) - 1;
for(int i = 0; i < chain[nr].size(); i++) {
aint[nr][ni[nr] + i + 1] = chain[nr][i];
//cout << ni + i + 1 << ' ' << aint[nr][ni + i + 1] << '\n' ;
update(nr, (ni[nr] + i + 1) / 2);
}
/*
cout << nr << " ";
for(int i = 1; i <= 4 * chain[nr].size(); i++)
cout << aint[nr][i] << ' ';
cout << '\n';
*/
}
void build() {
g[1].push_back(0);
dfs(1, 0);
for(int i = 1; i <= nrc; i++) {
reverse(chain[i].begin(), chain[i].end());
for(int j = 0; j < chain[i].size(); j++)
cpos[chain[i][j]] = j;
}
/*
for(int i = 1; i <= nrc; i++) {
for(int j = 0; j < chain[i].size(); j++) {
cout << chain[i][j] << ' ';
}
cout << '\n';
}
{1}
for(int i = 1; i <= n; i++)
cout << cpos[i] << ' ';
cout << '\n';
*/
for(int i = 1; i <= nrc; i++)
makeaint(i);
}
int aintquery(int nr, int from, int to) {
int ans = 0;
if(from == to) {
ans = aint[nr][from];
} else if(to > from) {
if(from % 2 == 1) {
if(v[ans] < v[aint[nr][from]])
ans = aint[nr][from];
from++;
}
if(to % 2 == 0) {
if(v[ans] < v[aint[nr][to]])
ans = aint[nr][to];
to--;
}
int pretender = aintquery(nr, from / 2, to / 2);
if(v[ans] < v[pretender])
ans = pretender;
}
return ans;
}
int main()
{
in >> n >> m;
for(int i = 1; i <= n; i++)
in >> v[i];
for(int i = 1; i < n; i++) {
int x, y;
in >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
}
build();
for(int i = 1; i <= m; i++) {
int op, x, y;
in >> op >> x >> y;
if(op == 0) {
int cch = cno[x];
v[x] = y;
update(cch, (ni[cch] + cpos[x] + 1) / 2);
} else if(op == 1) {
int cx = cno[x];
int cy = cno[y];
int stx = chain[cx][0];
int sty = chain[cy][0];
int res = 0;
while(1) {
if(cx == cy) {
if(cpos[x] > cpos[y])
swap(x, y);
int pretender = aintquery(cx, ni[cx] + cpos[x] + 1, ni[cy] + cpos[y] + 1);
if(v[res] < v[pretender])
res = pretender;
out << v[res] << '\n';
break;
} else {
if(levelg[parent[stx]] < levelg[parent[sty]]) {
swap(stx, sty);
swap(cx, cy);
swap(x, y);
}
int pretender = aintquery(cx, ni[cx] + 1, ni[cx] + cpos[x] + 1);
if(v[res] < v[pretender])
res = pretender;
x = parent[stx];
cx = cno[x];
stx = chain[cx][0];
}
}
} else {
assert(0);
}
}
in.close();
out.close();
return 0;
}