Pagini recente » Cod sursa (job #3330738) | Cod sursa (job #3347594) | Cod sursa (job #3330222) | Cod sursa (job #3343277) | Cod sursa (job #3350953)
#include <iostream>
#include <fstream>
#include <stdint.h>
const int32_t MAX_N = 100000;
const int32_t MAX_M = 100000;
const int32_t MAX_TREE = 1 << 18;
int32_t max(int32_t x, int32_t y) {
return (x > y) ? x : y;
}
int32_t LowestPow2(int32_t val) {
int32_t res = val - 1;
res |= res >> 1;
res |= res >> 2;
res |= res >> 4;
res |= res >> 8;
res |= res >> 16;
return res + 1;
}
struct SegTree {
int32_t n;
int32_t vals[MAX_TREE];
void Init(int32_t n) {
this->n = LowestPow2(n);
}
void AssignVal(int32_t ind, int32_t val) {
vals[ind + n] = val;
}
void Build() {
for(int32_t i = n - 1; i; --i)
vals[i] = max(vals[i << 1], vals[(i << 1) + 1]);
}
void SetVal(int32_t ind, int32_t val) {
ind += n;
vals[ind] = val;
for(ind >>= 1; ind; ind >>= 1)
vals[ind] = max(vals[ind << 1], vals[(ind << 1) + 1]);
}
int32_t GetMax(int32_t left, int32_t right) {
left += n;
right += n;
int32_t res = 0;
while(left <= right) {
if(left & 1)
res = max(res, vals[left++]);
left >>= 1;
if(!(right & 1))
res = max(res, vals[right--]);
right >>= 1;
}
return res;
}
};
struct Node {
int32_t val;
int32_t adjStart, parent;
int32_t depth, timeIn;
int32_t heavy, head;
};
struct AdjItem {
int32_t node;
int32_t next;
};
int32_t n, m;
Node nodes[MAX_N];
AdjItem adj[(MAX_N - 1) << 1];
SegTree maxTree;
int32_t GetPathMax(int32_t node1, int32_t node2) {
int32_t res = 0;
while(nodes[node1].head != nodes[node2].head) {
if(nodes[nodes[node1].head].depth > nodes[nodes[node2].head].depth)
std::swap(node1, node2);
int32_t head = nodes[node2].head;
res = max(res, maxTree.GetMax(nodes[head].timeIn, nodes[node2].timeIn));
node2 = nodes[head].parent;
}
if(nodes[node1].timeIn > nodes[node2].timeIn)
std::swap(node1, node2);
res = max(res, maxTree.GetMax(nodes[node1].timeIn, nodes[node2].timeIn));
return res;
}
void ReadData(std::istream& fin) {
fin >> n >> m;
for(int32_t i = 0; i != n; ++i) {
fin >> nodes[i].val;
nodes[i].adjStart = -1;
}
for(int32_t i = 0; i != n - 1; ++i) {
int32_t node1, node2;
fin >> node1 >> node2;
--node1; --node2;
adj[i << 1].node = node2;
adj[i << 1].next = nodes[node1].adjStart;
nodes[node1].adjStart = i << 1;
adj[(i << 1) + 1].node = node1;
adj[(i << 1) + 1].next = nodes[node2].adjStart;
nodes[node2].adjStart = (i << 1) + 1;
}
nodes[0].parent = -1;
nodes[0].depth = 0;
nodes[0].head = 0;
}
int32_t DFSFindHeavy(int32_t node) {
int32_t size = 1;
int32_t heavy = -1, heavySize = 0;
for(int32_t ind = nodes[node].adjStart; ind != -1; ind = adj[ind].next) {
int32_t next = adj[ind].node;
if(next == nodes[node].parent)
continue;
nodes[next].parent = node;
nodes[next].depth = nodes[node].depth + 1;
int32_t childSize = DFSFindHeavy(next);
size += childSize;
if(childSize > heavySize) {
heavy = next;
heavySize = childSize;
}
}
nodes[node].heavy = heavy;
return size;
}
void DFSLinearize(int32_t node) {
static int32_t globalTime = 0;
nodes[node].timeIn = globalTime++;
if(nodes[node].heavy == -1)
return;
nodes[nodes[node].heavy].head = nodes[node].head;
DFSLinearize(nodes[node].heavy);
for(int32_t ind = nodes[node].adjStart; ind != -1; ind = adj[ind].next) {
int32_t next = adj[ind].node;
if(next == nodes[node].parent || next == nodes[node].heavy)
continue;
nodes[next].head = next;
DFSLinearize(next);
}
}
void InitMaxTree() {
maxTree.Init(n);
for(int32_t i = 0; i != n; ++i)
maxTree.AssignVal(nodes[i].timeIn, nodes[i].val);
maxTree.Build();
}
void SolveQueries(std::istream& fin, std::ostream& fout) {
while(m--) {
int32_t t;
fin >> t;
if(t == 0) {
int32_t node, val;
fin >> node >> val;
--node;
nodes[node].val = val;
maxTree.SetVal(nodes[node].timeIn, val);
} else {
int32_t node1, node2;
fin >> node1 >> node2;
--node1; --node2;
fout << GetPathMax(node1, node2) << '\n';
}
}
}
int main() {
std::ifstream fin("heavypath.in");
std::ofstream fout("heavypath.out");
ReadData(fin);
DFSFindHeavy(0);
DFSLinearize(0);
InitMaxTree();
SolveQueries(fin, fout);
fin.close();
fout.close();
return 0;
}