1use competitive::prelude::*;
2use competitive::{
3 algebra::AdditiveOperation,
4 tree::{
5 LinkCutTree, LinkCutTreeSpec, LinkCutTreeSubtreeFold, LinkCutTreeSubtreeUpdate, TopTree,
6 TopTreeAction, TopTreeSpec,
7 },
8};
9
10struct SubtreeSum;
11
12struct SubtreeSumData {
13 value: u64,
14 virtual_sum: u64,
15 virtual_size: u64,
16 sum: u64,
17 size: u64,
18 lazy: u64,
19 virtual_lazy: u64,
20 path_parent_lazy: u64,
21}
22
23impl SubtreeSum {
24 fn apply(data: &mut SubtreeSumData, action: u64) {
25 if action == 0 {
26 return;
27 }
28 data.value += action;
29 data.virtual_sum += data.virtual_size * action;
30 data.sum += data.size * action;
31 data.lazy += action;
32 data.virtual_lazy += action;
33 }
34}
35
36impl LinkCutTreeSpec for SubtreeSum {
37 type Value = u64;
38 type Data = SubtreeSumData;
39
40 const ROOT_TO_NODE_TOP_DOWN: bool = false;
41
42 fn new(value: Self::Value) -> Self::Data {
43 SubtreeSumData {
44 value,
45 virtual_sum: 0,
46 virtual_size: 0,
47 sum: value,
48 size: 1,
49 lazy: 0,
50 virtual_lazy: 0,
51 path_parent_lazy: 0,
52 }
53 }
54
55 fn value(data: &Self::Data) -> &Self::Value {
56 &data.value
57 }
58
59 fn value_mut(data: &mut Self::Data) -> &mut Self::Value {
60 &mut data.value
61 }
62
63 fn top_down(data: &mut Self::Data, children: [Option<&mut Self::Data>; 2]) {
64 let action = std::mem::replace(&mut data.lazy, 0);
65 for child in children.into_iter().flatten() {
66 Self::apply(child, action);
67 }
68 }
69
70 fn bottom_up(data: &mut Self::Data, children: [Option<&Self::Data>; 2]) {
71 data.sum = data.value
72 + data.virtual_sum
73 + children
74 .into_iter()
75 .flatten()
76 .map(|child| child.sum)
77 .sum::<u64>();
78 data.size = 1
79 + data.virtual_size
80 + children
81 .into_iter()
82 .flatten()
83 .map(|child| child.size)
84 .sum::<u64>();
85 }
86
87 fn reverse(_data: &mut Self::Data) {}
88
89 fn attach_virtual(parent: &mut Self::Data, child: &mut Self::Data) {
90 child.path_parent_lazy = parent.virtual_lazy;
91 parent.virtual_sum += child.sum;
92 parent.virtual_size += child.size;
93 }
94
95 fn detach_virtual(parent: &mut Self::Data, child: &mut Self::Data) {
96 Self::apply(child, parent.virtual_lazy - child.path_parent_lazy);
97 parent.virtual_sum -= child.sum;
98 parent.virtual_size -= child.size;
99 }
100
101 fn transfer_path_parent(old_root: &mut Self::Data, new_root: &mut Self::Data) {
102 new_root.path_parent_lazy = std::mem::replace(&mut old_root.path_parent_lazy, 0);
103 }
104}
105
106impl LinkCutTreeSubtreeFold for SubtreeSum {
107 type Subtree = u64;
108
109 fn fold_subtree(data: &Self::Data) -> Self::Subtree {
110 data.sum
111 }
112}
113
114impl LinkCutTreeSubtreeUpdate for SubtreeSum {
115 type SubtreeAction = u64;
116
117 fn update_subtree(data: &mut Self::Data, action: &Self::SubtreeAction) {
118 Self::apply(data, *action);
119 }
120}
121
122struct TopTreeSubtreeSum;
123
124impl TopTreeSpec for TopTreeSubtreeSum {
125 type Info = u64;
126 type Point = (u64, u64);
127 type Path = (u64, u64, u64);
128
129 fn vertex(info: &Self::Info) -> Self::Path {
130 (*info, 1, 1)
131 }
132
133 fn add_vertex(point: &Self::Point, info: &Self::Info) -> Self::Path {
134 (point.0 + *info, point.1 + 1, 1)
135 }
136
137 fn add_edge(path: &Self::Path) -> Self::Point {
138 (path.0, path.1)
139 }
140
141 fn rake(left: &Self::Point, right: &Self::Point) -> Self::Point {
142 (left.0 + right.0, left.1 + right.1)
143 }
144
145 fn compress(left: &Self::Path, right: &Self::Path) -> Self::Path {
146 (left.0 + right.0, left.1 + right.1, left.2 + right.2)
147 }
148
149 fn reverse(_path: &mut Self::Path) {}
150}
151
152struct AddAction;
153
154impl TopTreeAction<TopTreeSubtreeSum> for AddAction {
155 type Action = u64;
156 type ActionMonoid = AdditiveOperation<u64>;
157
158 fn act_info(info: &mut u64, action: &Self::Action) {
159 *info += *action;
160 }
161
162 fn act_point(point: &mut (u64, u64), action: &Self::Action) {
163 point.0 += point.1 * *action;
164 }
165
166 fn act_path(path: &mut (u64, u64, u64), action: &Self::Action) {
167 path.0 += path.2 * *action;
168 }
169
170 fn act_path_light(path: &mut (u64, u64, u64), action: &Self::Action) {
171 path.0 += (path.1 - path.2) * *action;
172 }
173}
174
175competitive::define_enum_scan! {
176 enum Query: usize {
177 0 => Relink { u: usize, v: usize, w: usize, x: usize }
178 1 => Add { v: usize, p: usize, x: u64 }
179 2 => Sum { v: usize, p: usize }
180 }
181}
182
183#[verify::library_checker("dynamic_tree_subtree_add_subtree_sum")]
184pub fn dynamic_tree_subtree_add_subtree_sum(reader: impl Read, writer: impl Write) {
185 prepare_io!(reader, writer);
186 sc!(n, q, a: [u64; n], edges: [(usize, usize); n - 1]);
187 let mut tree = LinkCutTree::<SubtreeSum>::from_edges(a, &edges);
188 for _ in 0..q {
189 sc!(query: Query);
190 match query {
191 Query::Relink { u, v, w, x } => {
192 tree.cut(u, v);
193 tree.link(w, x);
194 }
195 Query::Add { v, p, x } => tree.update_subtree(v, p, &x),
196 Query::Sum { v, p } => {
197 pp!(tree.fold_subtree(v, p));
198 }
199 }
200 }
201}
202
203#[verify::library_checker("dynamic_tree_subtree_add_subtree_sum")]
204pub fn dynamic_tree_subtree_add_subtree_sum_top_tree(reader: impl Read, writer: impl Write) {
205 prepare_io!(reader, writer);
206 sc!(n, q, a: [u64; n], edges: [(usize, usize); n - 1]);
207 let mut tree = TopTree::<TopTreeSubtreeSum, AddAction>::from_edges(a, &edges);
208 for _ in 0..q {
209 sc!(query: Query);
210 match query {
211 Query::Relink { u, v, w, x } => {
212 tree.cut(u, v);
213 tree.link(w, x);
214 }
215 Query::Add { v, p, x } => tree.update_subtree(v, p, &x),
216 Query::Sum { v, p } => {
217 pp!(tree.fold_subtree(v, p).0);
218 }
219 }
220 }
221}