1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
//! ## HL分解(重軽分解)

use crate::utils::consts::INF;

/// HL分解
pub struct HLD {
    /// 頂点数
    pub N: usize,
    /// 根
    pub root: usize,
    /// グラフ
    pub G: Vec<Vec<usize>>,
    /// 親頂点
    pub parent: Vec<usize>,
    /// subtree_size[i] := `i`を根とする部分木のサイズ
    pub subtree_size: Vec<usize>,
    /// 行きがけ順での番号
    pub in_: Vec<usize>,
    /// 帰りがけ順での番号
    pub out: Vec<usize>,
    /// heavy pathの端点
    pub head: Vec<usize>,
}

impl HLD {
    /// `N`頂点の木を初期化する
    pub fn new(N: usize) -> Self {
        Self {
            N,
            root: INF,
            G: vec![vec![]; N],
            parent: vec![INF; N],
            subtree_size: vec![INF; N],
            in_: vec![INF; N],
            out: vec![INF; N],
            head: vec![INF; N],
        }
    }

    /// 辺`(u,v)`を追加する
    pub fn add_edge(&mut self, u: usize, v: usize) {
        self.G[u].push(v);
        self.G[v].push(u);
    }

    /// 頂点`root`を根としてHL分解をする
    pub fn decompose(&mut self, root: usize) {
        self.root = root;

        // heavy childの計算
        self.set_heavy_child(INF, root);

        // heavy pathの計算
        self.head[root] = root;
        self.build_heavy_path(INF, root, &mut 0);
    }

    /// 再帰的にheavy childを計算し,
    /// heavy childが`G[u][0]`にくるように設定する.
    ///
    /// (これにより,行きがけ順の走査で自然にheavy pathがえられる)
    fn set_heavy_child(&mut self, p: usize, u: usize) {
        self.parent[u] = p;
        self.subtree_size[u] = 1;

        for i in 0..self.G[u].len() {
            let v = self.G[u][i];
            if v == p {
                continue;
            }
            // 再帰的に計算
            self.set_heavy_child(u, v);

            // 部分木のサイズを足す
            self.subtree_size[u] += self.subtree_size[v];

            // G[u][0]にheavy childがくるようにswap
            let v_0 = self.G[u][0];
            if v_0 == p || self.subtree_size[v] > self.subtree_size[v_0] {
                self.G[u].swap(i, 0);
            }
        }
    }

    /// 行きがけ順に走査し,heavy pathの列を構築する
    fn build_heavy_path(&mut self, p: usize, u: usize, id: &mut usize) {
        self.in_[u] = *id;
        *id += 1;

        for i in 0..self.G[u].len() {
            let v = self.G[u][i];
            if v == p {
                continue;
            }
            self.head[v] = if i == 0 {
                // 自分がheavy childの場合
                self.head[u]
            } else {
                v
            };

            self.build_heavy_path(u, v, id);
        }

        self.out[u] = *id;
    }

    /// 頂点`v`の配列上でのインデックス
    #[inline]
    pub fn get_id(&self, v: usize) -> usize {
        self.in_[v]
    }

    /// 2頂点`u,v`の最小共通祖先 (LCA) を求める
    pub fn get_lca(&self, mut u: usize, mut v: usize) -> usize {
        let mut pu = self.head[u];
        let mut pv = self.head[v];

        while self.head[u] != self.head[v] {
            if self.in_[pu] > self.in_[pv] {
                u = self.parent[pu];
                pu = self.head[u];
            } else {
                v = self.parent[pv];
                pv = self.head[v];
            }
        }

        if self.in_[u] <= self.in_[v] {
            u
        } else {
            v
        }
    }

    /// `u`を根とする部分木の値を集約する
    ///
    /// (モノイド`M`が可環であるときに定義される)
    ///
    /// **戻り値**
    /// - `(usize, usize)` : (左, 右)
    #[inline]
    pub fn get_subtree<T, F>(&self, u: usize) -> (usize, usize) {
        (self.in_[u], self.out[u])
    }

    /// 頂点`u,v`間のパス上のパス断片を順に返すイテレータを返す.
    ///
    /// **戻り値 (Item)**
    /// - `i (usize)` : 最も根側の頂点
    /// - `j (usize)` : 最も葉側の頂点
    /// - `last (bool)` : 最後のpath segmentであるか
    /// - `rev (bool)` : 取得するpathの向きに対してpath segmentが逆方向かどうか
    pub fn get_path(&self, u: usize, v: usize) -> PathSegment<'_> {
        PathSegment {
            hld: self,
            from: u,
            to: v,
            exhasted: false,
        }
    }
}

/// パス断片を返すイテレータ
///
/// **戻り値 (next)**
/// - `i (usize)` : 最も根側の頂点
/// - `j (usize)` : 最も葉側の頂点
/// - `last (bool)` : 最後のpath segmentであるか
/// - `rev (bool)` : 取得するpathの向きに対してpath segmentが逆方向かどうか
///
/// **参考**
/// - <https://ngtkana.hatenablog.com/entry/2024/06/24/200138>
pub struct PathSegment<'a> {
    hld: &'a HLD,
    from: usize,
    to: usize,
    exhasted: bool,
}

impl Iterator for PathSegment<'_> {
    type Item = (usize, usize, bool, bool);

    fn next(&mut self) -> Option<Self::Item> {
        let Self {
            hld,
            from,
            to,
            exhasted,
        } = *self;

        if exhasted {
            return None;
        }

        let HLD {
            in_, head, parent, ..
        } = hld;

        Some(if head[from] == head[to] {
            self.exhasted = true;
            if in_[from] < in_[to] {
                (from, to, true, false)
            } else {
                (to, from, true, true)
            }
        } else if in_[from] < in_[to] {
            self.to = parent[head[to]];
            (head[to], to, false, false)
        } else {
            self.from = parent[head[from]];
            (head[from], from, false, true)
        })
    }
}