#line 1 "main.cpp" /** * @title Template */ #include #include #include #include #include #include #line 2 "/Users/kodamankod/Desktop/Programming/Library/other/chmin_chmax.cpp" template constexpr bool chmin(T &lhs, const U &rhs) { if (lhs > rhs) { lhs = rhs; return true; } return false; } template constexpr bool chmax(T &lhs, const U &rhs) { if (lhs < rhs) { lhs = rhs; return true; } return false; } /** * @title Chmin/Chmax */ #line 2 "/Users/kodamankod/Desktop/Programming/Library/other/range.cpp" #line 4 "/Users/kodamankod/Desktop/Programming/Library/other/range.cpp" class range { public: class iterator { private: int64_t M_position; public: constexpr iterator(int64_t position) noexcept: M_position(position) { } constexpr void operator ++ () noexcept { ++M_position; } constexpr bool operator != (iterator other) const noexcept { return M_position != other.M_position; } constexpr int64_t operator * () const noexcept { return M_position; } }; class reverse_iterator { private: int64_t M_position; public: constexpr reverse_iterator(int64_t position) noexcept: M_position(position) { } constexpr void operator ++ () noexcept { --M_position; } constexpr bool operator != (reverse_iterator other) const noexcept { return M_position != other.M_position; } constexpr int64_t operator * () const noexcept { return M_position; } }; private: const iterator M_first, M_last; public: constexpr range(int64_t first, int64_t last) noexcept: M_first(first), M_last(std::max(first, last)) { } constexpr iterator begin() const noexcept { return M_first; } constexpr iterator end() const noexcept { return M_last; } constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(*M_last - 1); } constexpr reverse_iterator rend() const noexcept { return reverse_iterator(*M_first - 1); } }; /** * @title Range */ #line 2 "/Users/kodamankod/Desktop/Programming/Library/other/rev.cpp" #include #include #line 6 "/Users/kodamankod/Desktop/Programming/Library/other/rev.cpp" template class rev_impl { public: using iterator = typename std::decay::type::reverse_iterator; private: const iterator M_begin; const iterator M_end; public: constexpr rev_impl(T &&cont) noexcept: M_begin(std::rbegin(cont)), M_end(std::rend(cont)) { } constexpr iterator begin() const noexcept { return M_begin; } constexpr iterator end() const noexcept { return M_end; } }; template constexpr decltype(auto) rev(T &&cont) { return rev_impl(std::forward(cont)); } /** * @title Reverser */ #line 2 "/Users/kodamankod/Desktop/Programming/Library/other/fix_point.cpp" #line 4 "/Users/kodamankod/Desktop/Programming/Library/other/fix_point.cpp" template struct fix_point_impl: private Func { explicit constexpr fix_point_impl(Func &&func): Func(std::forward(func)) { } template constexpr decltype(auto) operator () (Args &&... args) const { return Func::operator()(*this, std::forward(args)...); } }; template constexpr decltype(auto) fix_point(Func &&func) { return fix_point_impl(std::forward(func)); } /** * @title Lambda Recursion */ #line 2 "/Users/kodamankod/Desktop/Programming/Library/graph/heavy_light_decomposition.cpp" #include #line 6 "/Users/kodamankod/Desktop/Programming/Library/graph/heavy_light_decomposition.cpp" class heavy_light_decomposition { public: using size_type = size_t; private: std::vector> M_graph; std::vector M_size, M_parent, M_head; size_type M_index; void M_calc_subtree(size_type u, size_type p) { M_size[u] = 1; for (auto v: M_graph[u]) { if (v != p) { M_calc_subtree(v, u); M_size[u] += M_size[v]; } } } void M_decompose(size_type u, size_type p, size_type h) { label[u] = M_index; M_head[u] = h; M_parent[u] = p; ++M_index; size_type max = 0, heavy = -1; for (auto v: M_graph[u]) { if (v != p) { if (max < M_size[v]) { max = M_size[v]; heavy = v; } } } if (heavy == size_type(-1)) return; M_decompose(heavy, u, h); for (auto v: M_graph[u]) { if (v != p && v != heavy) { M_decompose(v, u, v); } } } public: std::vector label; heavy_light_decomposition() { } explicit heavy_light_decomposition(size_type size) { initialize(size); } void initialize(size_type size) { clear(); M_index = 0; M_graph.assign(size, { }); M_size.assign(size, 0); M_parent.assign(size, 0); M_head.assign(size, 0); label.assign(size, 0); } void construct(size_type root = 0) { M_calc_subtree(root, -1); M_decompose(root, -1, root); } void add_edge(size_type u, size_type v) { M_graph[u].push_back(v); M_graph[v].push_back(u); } template void each_edge(size_type u, size_type v, const Func &func) const { while (true) { if (label[u] > label[v]) { std::swap(u, v); } if (M_head[u] == M_head[v]) { if (label[u] + 1 <= label[v]) { func(label[u] + 1, label[v]); } return; } func(label[M_head[v]], label[v]); v = M_parent[M_head[v]]; } } template void each_vertex(size_type u, size_type v, const Func &func) const { while (true) { if (label[u] > label[v]) { std::swap(u, v); } if (M_head[u] == M_head[v]) { func(label[u], label[v]); return; } func(label[M_head[v]], label[v]); v = M_parent[M_head[v]]; } } size_type lca(size_type u, size_type v) const { if (label[u] > label[v]) { std::swap(u, v); } while (label[u] <= label[v]) { if (M_head[u] == M_head[v]) { return u; } v = M_parent[M_head[v]]; } return v; } size_type size() const { return M_graph.size(); } bool empty() const { return M_graph.empty(); } void clear() { M_index = 0; M_graph.clear(); M_graph.shrink_to_fit(); M_size.clear(); M_size.shrink_to_fit(); M_parent.clear(); M_parent.shrink_to_fit(); M_head.clear(); M_head.shrink_to_fit(); label.clear(); label.shrink_to_fit(); } }; /** * @title Heavy-Light Decomposition */ #line 2 "/Users/kodamankod/Desktop/Programming/Library/container/segment_tree.cpp" #line 1 "/Users/kodamankod/Desktop/Programming/Library/other/monoid.cpp" #include #line 4 "/Users/kodamankod/Desktop/Programming/Library/other/monoid.cpp" template class has_identity: public std::false_type { }; template class has_identity::type>: public std::true_type { }; template class fixed_monoid_impl: public T { public: static constexpr typename T::type convert(const typename T::type &value) { return value; } static constexpr typename T::type revert(const typename T::type &value) { return value; } }; template class fixed_monoid_impl: private T { public: class type { public: typename T::type value; bool state; explicit constexpr type(): value(typename T::type { }), state(false) { } explicit constexpr type(const typename T::type &value): value(value), state(true) { } }; static constexpr type convert(const typename T::type &value) { return type(value); } static constexpr typename T::type revert(const type &value) { return value.value; } static constexpr type identity() { return type(); } static constexpr type operation(const type &v1, const type &v2) { if (!v1.state) return v2; if (!v2.state) return v1; return type(T::operation(v1.value, v2.value)); } }; template using fixed_monoid = fixed_monoid_impl::value>; template class fixed_combined_monoid_impl { public: using value_structure = typename T::value_structure; using operator_structure = fixed_monoid; template static constexpr typename value_structure::type operation( const typename value_structure::type &val, const typename operator_structure::type &op, Args&&... args) { return T::opration(val, op, std::forward(args)...); } }; template class fixed_combined_monoid_impl { public: using value_structure = typename T::value_structure; using operator_structure = fixed_monoid; template static constexpr typename value_structure::type operation( const typename value_structure::type &val, const typename operator_structure::type &op, Args&&... args) { if (!op.state) return val; return T::operation(val, op.value, std::forward(args)...); } }; template using fixed_combined_monoid = fixed_combined_monoid_impl::value>; #line 8 "/Users/kodamankod/Desktop/Programming/Library/container/segment_tree.cpp" template class segment_tree { public: using structure = Monoid; using value_monoid = typename Monoid::value_structure; using value_type = typename Monoid::value_structure::type; using size_type = size_t; private: using fixed_value_monoid = fixed_monoid; using fixed_value_type = typename fixed_value_monoid::type; std::vector M_tree; void M_fix_change(const size_type index) { M_tree[index] = fixed_value_monoid::operation(M_tree[index << 1 | 0], M_tree[index << 1 | 1]); } public: segment_tree() = default; explicit segment_tree(const size_type size) { initialize(size); } template explicit segment_tree(InputIterator first, InputIterator last) { construct(first, last); } void initialize(const size_type size) { clear(); M_tree.assign(size << 1, fixed_value_monoid::identity()); } template void construct(InputIterator first, InputIterator last) { clear(); const size_type size = std::distance(first, last); M_tree.reserve(size << 1); M_tree.assign(size, fixed_value_monoid::identity()); std::transform(first, last, std::back_inserter(M_tree), [&](const value_type &value) { return fixed_value_monoid::convert(value); }); for (size_type index = size - 1; index != 0; --index) { M_fix_change(index); } } void assign(size_type index, const value_type &value) { index += size(); M_tree[index] = fixed_value_monoid::convert(value); while (index != 1) { index >>= 1; M_fix_change(index); } } value_type at(const size_type index) const { return fixed_value_monoid::revert(M_tree[index + size()]); } value_type fold(size_type first, size_type last) const { first += size(); last += size(); fixed_value_type fold_l = fixed_value_monoid::identity(); fixed_value_type fold_r = fixed_value_monoid::identity(); while (first != last) { if (first & 1) { fold_l = fixed_value_monoid::operation(fold_l, M_tree[first]); ++first; } if (last & 1) { --last; fold_r = fixed_value_monoid::operation(M_tree[last], fold_r); } first >>= 1; last >>= 1; } return fixed_value_monoid::revert(fixed_value_monoid::operation(fold_l, fold_r)); } void clear() { M_tree.clear(); M_tree.shrink_to_fit(); } size_type size() const { return M_tree.size() >> 1; } }; /** * @title Segment Tree */ #line 19 "main.cpp" using i32 = int32_t; using i64 = int64_t; using u32 = uint32_t; using u64 = uint64_t; constexpr i32 inf32 = (i32(1) << 30) - 1; constexpr i64 inf64 = (i64(1) << 62) - 1; struct st_monoid { static inline heavy_light_decomposition *hld = nullptr; struct value_structure { using type = i32; static type operation(const type& v1, const type& v2) { return hld -> lca(v1, v2); } }; }; int main() { i32 N, K, Q; std::cin >> N >> K >> Q; std::vector vivace(N); std::vector> graph(N); for (auto &x: vivace) { std::cin >> x; } std::vector lives(K); for (i32 &x: lives) { std::cin >> x; --x; } heavy_light_decomposition hld(N); st_monoid::hld = &hld; for (auto i: range(0, N - 1)) { i32 a, b; std::cin >> a >> b; --a; --b; graph[a].push_back(b); graph[b].push_back(a); hld.add_edge(a, b); } hld.construct(); segment_tree seg(K); for (i32 i: range(0, K)) { seg.assign(i, lives[i]); } fix_point([&](auto dfs, i32 u, i32 p) -> void { if (p != -1) { chmax(vivace[u], vivace[p]); } for (auto v: graph[u]) { if (v != p) { dfs(v, u); } } })(0, -1); while (Q--) { i32 type; std::cin >> type; if (type == 1) { i32 x, y; std::cin >> x >> y; --x; --y; seg.assign(x, y); } else { i32 l, r; std::cin >> l >> r; --l; std::cout << vivace[seg.fold(l, r)] << '\n'; } } return 0; }