結果
| 問題 |
No.1030 だんしんぐぱーりない
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2020-05-02 01:16:46 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 477 ms / 2,000 ms |
| コード長 | 5,822 bytes |
| コンパイル時間 | 1,507 ms |
| コンパイル使用メモリ | 104,892 KB |
| 最終ジャッジ日時 | 2025-01-10 05:42:28 |
|
ジャッジサーバーID (参考情報) |
judge3 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 40 |
ソースコード
#include <iostream>
#include <vector>
#include <functional>
template <class Cost = int>
struct Edge {
int src, dst;
Cost cost;
Edge(int src = -1, int dst = -1, Cost cost = 1)
: src(src), dst(dst), cost(cost){};
bool operator<(const Edge<Cost>& e) const { return this->cost < e.cost; }
bool operator>(const Edge<Cost>& e) const { return this->cost > e.cost; }
};
template <class Cost = int>
struct Graph {
std::vector<std::vector<Edge<Cost>>> graph;
Graph(int n = 0) : graph(n) {}
void span(bool direct, int src, int dst, Cost cost = 1) {
graph[src].emplace_back(src, dst, cost);
if (!direct) graph[dst].emplace_back(dst, src, cost);
}
std::vector<Edge<Cost>>& operator[](int v) { return graph[v]; }
std::vector<Edge<Cost>> operator[](int v) const { return graph[v]; }
int size() const { return graph.size(); }
};
template <class Cost = int>
struct LevelAncestor {
Graph<Cost> tree;
std::vector<std::vector<int>> par;
std::vector<int> depth;
std::vector<Cost> cdepth;
int kmax;
void dfs(int v, int p = -1, int d = 0, Cost c = 0) {
par[v][0] = p;
depth[v] = d;
cdepth[v] = c;
for (const auto& e : tree[v]) {
if (e.dst == p) continue;
dfs(e.dst, v, d + 1, c + e.cost);
}
}
LevelAncestor(const Graph<Cost>& tree, int root)
: tree(tree), par(tree.size()), depth(tree.size(), -1), cdepth(tree.size()) {
kmax = 0;
while ((1 << kmax) < (int)tree.size()) ++kmax;
for (auto& v : par) v.resize(kmax + 1);
dfs(root);
for (int k = 1; k <= kmax; ++k) {
for (int v = 0; v < tree.size(); ++v) {
int p = par[v][k - 1];
par[v][k] = (p == -1 ? -1 : par[p][k - 1]);
}
}
}
int climb(int v, int d) const {
for (int k = kmax; k >= 0 && v != -1; --k) {
if ((1 << k) > d) continue;
v = par[v][k];
d -= (1 << k);
}
return v;
}
int lca(int u, int v) const {
if (depth[u] < depth[v]) std::swap(u, v);
if (depth[u] > depth[v]) {
u = climb(u, depth[u] - depth[v]);
}
if (u == v) return u;
for (int k = kmax; k >= 0; --k) {
if (par[u][k] != par[v][k]) {
u = par[u][k];
v = par[v][k];
}
}
return par[u][0];
}
int dist(int u, int v) const {
int p = lca(u, v);
return depth[u] + depth[v] - depth[p] * 2;
}
Cost cdist(int u, int v) const {
int p = lca(u, v);
return cdepth[u] + cdepth[v] - cdepth[p] * 2;
}
};
template <class T>
struct SegmentTree {
using Merger = std::function<T(T, T)>;
int length;
std::vector<T> dat;
T unit;
Merger merge;
explicit SegmentTree(int n, const T& unit, const Merger& merge)
: length(1), unit(unit), merge(merge) {
while (length < n) length <<= 1;
dat.assign(length * 2, unit);
}
template <class Container>
explicit SegmentTree(const Container& elems, const T& unit, const Merger& merge)
: length(1), unit(unit), merge(merge) {
int n = elems.size();
while (length < n) length <<= 1;
dat.assign(length * 2, unit);
std::copy(elems.begin(), elems.end(), dat.begin() + length);
for (int nidx = length - 1; nidx >= 1; --nidx) {
T vl = dat[nidx * 2 + 0];
T vr = dat[nidx * 2 + 1];
dat[nidx] = merge(vl, vr);
}
}
void update(int nidx, const T& elem) {
nidx += length;
dat[nidx] = elem;
while (nidx > 0) {
nidx >>= 1;
T vl = dat[nidx * 2 + 0];
T vr = dat[nidx * 2 + 1];
dat[nidx] = merge(vl, vr);
}
}
T fold(int ql, int qr) {
ql = std::max(ql, 0);
qr = std::min(qr, length);
ql += length, qr += length;
T lacc = unit, racc = unit;
while (ql < qr) {
if (ql & 1) {
lacc = merge(lacc, dat[ql]);
++ql;
}
if (qr & 1) {
--qr;
racc = merge(dat[qr], racc);
}
ql >>= 1, qr >>= 1;
}
return merge(lacc, racc);
}
T get(int idx) { return dat[idx + length]; }
T whole() { return dat[1]; }
};
void solve() {
int n, k, q;
std::cin >> n >> k >> q;
std::vector<int> cs(n);
for (auto& c : cs) std::cin >> c;
std::vector<int> vs(k);
for (auto& v : vs) {
std::cin >> v;
--v;
}
Graph<> graph(n);
for (int i = 0; i < n - 1; ++i) {
int u, v;
std::cin >> u >> v;
graph.span(false, --u, --v);
}
{
std::function<void(int, int)>
dfs = [&](int v, int p) -> void {
for (auto e : graph[v]) {
int u = e.dst;
if (u == p) continue;
cs[u] = std::max(cs[u], cs[v]);
dfs(u, v);
}
};
dfs(0, -1);
}
LevelAncestor<> la(graph, 0);
SegmentTree<int>
seg(vs, -1,
[&](int u, int v) {
if (u > v) std::swap(u, v);
return (u == -1 ? v : la.lca(u, v));
});
while (q--) {
int t;
std::cin >> t;
if (t == 1) {
int i, v;
std::cin >> i >> v;
seg.update(--i, --v);
} else {
int l, r;
std::cin >> l >> r;
std::cout << cs[seg.fold(--l, r)] << std::endl;
}
}
}
int main() {
std::cin.tie(nullptr);
std::ios::sync_with_stdio(false);
solve();
return 0;
}