library_checker/tree/
dynamic_tree_vertex_set_path_composite.rs1use competitive::prelude::*;
2use competitive::{
3 algebra::{Associative, EmptyAct, LazyMapMonoid, LinearOperation, Magma, Unital},
4 num::mint_basic::MInt998244353 as M,
5 tree::{PathLinkCutTree, TopTree, TopTreeSpec},
6};
7
8type Affine = (M, M);
9
10struct BidirectionalAffine;
11
12impl Magma for BidirectionalAffine {
13 type T = (Affine, Affine);
14
15 fn operate(left: &Self::T, right: &Self::T) -> Self::T {
16 (
17 LinearOperation::operate(&left.0, &right.0),
18 LinearOperation::operate(&right.1, &left.1),
19 )
20 }
21}
22
23impl Unital for BidirectionalAffine {
24 fn unit() -> Self::T {
25 let unit = LinearOperation::unit();
26 (unit, unit)
27 }
28}
29
30impl Associative for BidirectionalAffine {}
31
32struct PathComposite;
33
34impl LazyMapMonoid for PathComposite {
35 type Key = Affine;
36 type Agg = (Affine, Affine);
37 type Act = ();
38 type AggMonoid = BidirectionalAffine;
39 type ActMonoid = ();
40 type KeyAct = EmptyAct<Affine>;
41
42 fn single_agg(key: &Self::Key) -> Self::Agg {
43 (*key, *key)
44 }
45
46 fn toggle(value: &mut Self::Agg) {
47 std::mem::swap(&mut value.0, &mut value.1);
48 }
49
50 fn act_agg(value: &Self::Agg, _action: &Self::Act) -> Option<Self::Agg> {
51 Some(*value)
52 }
53}
54
55impl TopTreeSpec for PathComposite {
56 type Info = Affine;
57 type Point = ();
58 type Path = (Affine, Affine);
59
60 fn vertex(info: &Self::Info) -> Self::Path {
61 (*info, *info)
62 }
63
64 fn add_vertex(_point: &Self::Point, info: &Self::Info) -> Self::Path {
65 (*info, *info)
66 }
67
68 fn add_edge(_path: &Self::Path) -> Self::Point {}
69
70 fn rake(_left: &Self::Point, _right: &Self::Point) -> Self::Point {}
71
72 fn compress(left: &Self::Path, right: &Self::Path) -> Self::Path {
73 BidirectionalAffine::operate(left, right)
74 }
75
76 fn reverse(path: &mut Self::Path) {
77 std::mem::swap(&mut path.0, &mut path.1);
78 }
79}
80
81competitive::define_enum_scan! {
82 enum Query: usize {
83 0 => Relink { u: usize, v: usize, w: usize, x: usize }
84 1 => Set { p: usize, cd: Affine }
85 2 => Apply { u: usize, v: usize, x: M }
86 }
87}
88
89#[verify::library_checker("dynamic_tree_vertex_set_path_composite")]
90pub fn dynamic_tree_vertex_set_path_composite(reader: impl Read, writer: impl Write) {
91 prepare_io!(reader, writer);
92 sc!(n, q, ab: [Affine; n], edges: [(usize, usize); n - 1]);
93 let mut tree = PathLinkCutTree::<PathComposite>::from_edges(ab, &edges);
94 for _ in 0..q {
95 sc!(query: Query);
96 match query {
97 Query::Relink { u, v, w, x } => {
98 tree.cut(u, v);
99 tree.link(w, x);
100 }
101 Query::Set { p, cd } => tree.set(p, cd),
102 Query::Apply { u, v, x } => {
103 pp!(LinearOperation::apply(&tree.fold_path(u, v).0, &x));
104 }
105 }
106 }
107}
108
109#[verify::library_checker("dynamic_tree_vertex_set_path_composite")]
110pub fn dynamic_tree_vertex_set_path_composite_top_tree(reader: impl Read, writer: impl Write) {
111 prepare_io!(reader, writer);
112 sc!(n, q, ab: [Affine; n], edges: [(usize, usize); n - 1]);
113 let mut tree = TopTree::<PathComposite>::from_edges(ab, &edges);
114 for _ in 0..q {
115 sc!(query: Query);
116 match query {
117 Query::Relink { u, v, w, x } => {
118 tree.cut(u, v);
119 tree.link(w, x);
120 }
121 Query::Set { p, cd } => tree.set(p, cd),
122 Query::Apply { u, v, x } => {
123 pp!(LinearOperation::apply(&tree.fold_path(u, v).0, &x));
124 }
125 }
126 }
127}