結果
問題 | No.1030 だんしんぐぱーりない |
ユーザー | KoD |
提出日時 | 2020-08-03 12:20:41 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 453 ms / 2,000 ms |
コード長 | 13,458 bytes |
コンパイル時間 | 1,729 ms |
コンパイル使用メモリ | 104,244 KB |
実行使用メモリ | 20,472 KB |
最終ジャッジ日時 | 2024-07-22 07:41:39 |
合計ジャッジ時間 | 15,194 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,248 KB |
testcase_02 | AC | 2 ms
5,248 KB |
testcase_03 | AC | 2 ms
5,376 KB |
testcase_04 | AC | 2 ms
5,376 KB |
testcase_05 | AC | 344 ms
17,920 KB |
testcase_06 | AC | 262 ms
14,336 KB |
testcase_07 | AC | 171 ms
8,192 KB |
testcase_08 | AC | 175 ms
9,600 KB |
testcase_09 | AC | 285 ms
17,920 KB |
testcase_10 | AC | 118 ms
5,632 KB |
testcase_11 | AC | 271 ms
11,264 KB |
testcase_12 | AC | 309 ms
16,000 KB |
testcase_13 | AC | 248 ms
14,848 KB |
testcase_14 | AC | 316 ms
14,592 KB |
testcase_15 | AC | 141 ms
5,376 KB |
testcase_16 | AC | 280 ms
12,672 KB |
testcase_17 | AC | 297 ms
18,176 KB |
testcase_18 | AC | 349 ms
15,104 KB |
testcase_19 | AC | 187 ms
7,168 KB |
testcase_20 | AC | 221 ms
10,880 KB |
testcase_21 | AC | 228 ms
13,952 KB |
testcase_22 | AC | 224 ms
11,264 KB |
testcase_23 | AC | 265 ms
10,496 KB |
testcase_24 | AC | 194 ms
6,784 KB |
testcase_25 | AC | 236 ms
10,496 KB |
testcase_26 | AC | 155 ms
5,376 KB |
testcase_27 | AC | 176 ms
5,376 KB |
testcase_28 | AC | 302 ms
13,440 KB |
testcase_29 | AC | 231 ms
15,872 KB |
testcase_30 | AC | 209 ms
11,520 KB |
testcase_31 | AC | 211 ms
10,496 KB |
testcase_32 | AC | 271 ms
14,592 KB |
testcase_33 | AC | 290 ms
16,768 KB |
testcase_34 | AC | 117 ms
6,016 KB |
testcase_35 | AC | 453 ms
20,352 KB |
testcase_36 | AC | 450 ms
20,352 KB |
testcase_37 | AC | 434 ms
20,352 KB |
testcase_38 | AC | 451 ms
20,472 KB |
testcase_39 | AC | 443 ms
20,352 KB |
testcase_40 | AC | 2 ms
5,376 KB |
testcase_41 | AC | 2 ms
5,376 KB |
ソースコード
#line 1 "main.cpp" /** * @title Template */ #include <iostream> #include <algorithm> #include <utility> #include <numeric> #include <vector> #include <array> #line 2 "/Users/kodamankod/Desktop/Programming/Library/other/chmin_chmax.cpp" template <class T, class U> constexpr bool chmin(T &lhs, const U &rhs) { if (lhs > rhs) { lhs = rhs; return true; } return false; } template <class T, class U> 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 <type_traits> #include <iterator> #line 6 "/Users/kodamankod/Desktop/Programming/Library/other/rev.cpp" template <class T> class rev_impl { public: using iterator = typename std::decay<T>::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 <class T> constexpr decltype(auto) rev(T &&cont) { return rev_impl<T>(std::forward<T>(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 <class Func> struct fix_point_impl: private Func { explicit constexpr fix_point_impl(Func &&func): Func(std::forward<Func>(func)) { } template <class... Args> constexpr decltype(auto) operator () (Args &&... args) const { return Func::operator()(*this, std::forward<Args>(args)...); } }; template <class Func> constexpr decltype(auto) fix_point(Func &&func) { return fix_point_impl<Func>(std::forward<Func>(func)); } /** * @title Lambda Recursion */ #line 2 "/Users/kodamankod/Desktop/Programming/Library/graph/heavy_light_decomposition.cpp" #include <cstddef> #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<std::vector<size_type>> M_graph; std::vector<size_type> 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<size_type> 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 <class Func> 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 <class Func> 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 <type_traits> #line 4 "/Users/kodamankod/Desktop/Programming/Library/other/monoid.cpp" template <class T, class = void> class has_identity: public std::false_type { }; template <class T> class has_identity<T, typename std::conditional<false, decltype(T::identity()), void>::type>: public std::true_type { }; template <class T, bool HasIdentity> 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 T> class fixed_monoid_impl<T, false>: 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 <class T> using fixed_monoid = fixed_monoid_impl<T, has_identity<T>::value>; template <class T, bool HasIdentity> class fixed_combined_monoid_impl { public: using value_structure = typename T::value_structure; using operator_structure = fixed_monoid<typename T::operator_structure>; template <class... Args> 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>(args)...); } }; template <class T> class fixed_combined_monoid_impl<T, false> { public: using value_structure = typename T::value_structure; using operator_structure = fixed_monoid<typename T::operator_structure>; template <class... Args> 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>(args)...); } }; template <class T> using fixed_combined_monoid = fixed_combined_monoid_impl<T, has_identity<typename T::operator_structure>::value>; #line 8 "/Users/kodamankod/Desktop/Programming/Library/container/segment_tree.cpp" template <class Monoid> 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<value_monoid>; using fixed_value_type = typename fixed_value_monoid::type; std::vector<fixed_value_type> 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 <class InputIterator> 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 <class InputIterator> 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<i32> vivace(N); std::vector<std::vector<i32>> graph(N); for (auto &x: vivace) { std::cin >> x; } std::vector<i32> 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<st_monoid> 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; }