cp_library_rs/data_structure/
dynamic_segment_tree_2d.rs

1//! 2D dynamic segment tree(implicit,交互 2 分木 + split 軸キャッシュ)
2//!
3//! 方針:
4//! - 本体 API は `apply(rx, ry, act)` と `get_range(rx, ry)`
5//! - `get(x, y)` は `get_range(x..x+1, y..y+1)` のラッパー
6//! - 重要:ノードごとに「このノードはどちらの軸で split するか」を 1 度だけ決めて保持する
7//!   - クエリ依存の軸選択は「未決定ノードの初回 split 決定」にだけ使う
8//!   - これにより `left/right` が表す領域の意味が常に一意になり,正しさが保たれる
9//! - split 不能(軸長 1)なら反転して試す,両方不能なら真の葉
10//! - `ActedMonoidWithSize::e_with_size(len)` の `len` は「面積 area」とみなす
11
12use std::fmt::Debug;
13use std::ops::{Bound::*, RangeBounds};
14
15use num::ToPrimitive;
16use num_traits::PrimInt;
17
18use crate::{
19    algebraic_structure::actedmonoid_with_size::ActedMonoidWithSize,
20    tree::arena::{Arena, ArenaNode, Ptr},
21};
22
23type Range<I> = (I, I);
24type Rect<I> = (Range<I>, Range<I>);
25
26type A<M> = Arena<NodeInner<M>>;
27
28#[derive(Clone, Copy, Debug, PartialEq, Eq)]
29enum Axis {
30    X,
31    Y,
32}
33impl Axis {
34    #[inline]
35    fn flip(self) -> Self {
36        match self {
37            Axis::X => Axis::Y,
38            Axis::Y => Axis::X,
39        }
40    }
41}
42
43// ========== node ==========
44
45struct NodeInner<M: ActedMonoidWithSize> {
46    sum: M::Val,
47    act: M::Act,
48    left: Option<Ptr>,
49    right: Option<Ptr>,
50    /// このノードの split 軸(未決定なら `None`)
51    split_axis: Option<Axis>,
52}
53
54impl<M: ActedMonoidWithSize> ArenaNode for NodeInner<M> {}
55
56impl<M: ActedMonoidWithSize> NodeInner<M> {
57    fn with_area(area: usize) -> Self {
58        Self {
59            sum: M::e_with_size(area),
60            act: M::id(),
61            left: None,
62            right: None,
63            split_axis: None,
64        }
65    }
66}
67
68// ========== main structure ==========
69
70pub struct DynamicSegmentTree2D<I: PrimInt, M: ActedMonoidWithSize> {
71    xmin: I,
72    xmax: I,
73    ymin: I,
74    ymax: I,
75
76    arena: A<M>,
77    root: Option<Ptr>,
78}
79
80impl<I, M> DynamicSegmentTree2D<I, M>
81where
82    I: PrimInt + ToPrimitive + Debug,
83    M: ActedMonoidWithSize,
84{
85    pub fn new((xmin, xmax): Range<I>, (ymin, ymax): Range<I>) -> Self {
86        assert!(xmin < xmax);
87        assert!(ymin < ymax);
88        Self {
89            xmin,
90            xmax,
91            ymin,
92            ymax,
93            arena: A::new(),
94            root: None,
95        }
96    }
97
98    // ---------- public API ----------
99
100    /// 矩形 apply(遅延)
101    pub fn apply<RX, RY>(&mut self, rx: RX, ry: RY, act: M::Act)
102    where
103        RX: RangeBounds<I> + Debug,
104        RY: RangeBounds<I> + Debug,
105    {
106        let (qxl, qxr) = self
107            .parse_range_x(&rx)
108            .unwrap_or_else(|| panic!("bad x-range: {:?}", rx));
109        let (qyl, qyr) = self
110            .parse_range_y(&ry)
111            .unwrap_or_else(|| panic!("bad y-range: {:?}", ry));
112
113        let root = self.root.take();
114        self.root = self.apply_inner(
115            root,
116            ((self.xmin, self.xmax), (self.ymin, self.ymax)),
117            ((qxl, qxr), (qyl, qyr)),
118            &act,
119            Axis::X,
120        );
121    }
122
123    /// 矩形 query(遅延があるので `&mut self`)
124    pub fn get_range<RX, RY>(&mut self, rx: RX, ry: RY) -> M::Val
125    where
126        RX: RangeBounds<I> + Debug,
127        RY: RangeBounds<I> + Debug,
128    {
129        let (qxl, qxr) = self
130            .parse_range_x(&rx)
131            .unwrap_or_else(|| panic!("bad x-range: {:?}", rx));
132        let (qyl, qyr) = self
133            .parse_range_y(&ry)
134            .unwrap_or_else(|| panic!("bad y-range: {:?}", ry));
135
136        self.get_range_inner(
137            self.root,
138            ((self.xmin, self.xmax), (self.ymin, self.ymax)),
139            ((qxl, qxr), (qyl, qyr)),
140            Axis::X,
141        )
142    }
143
144    /// 点取得:`get_range(x..x+1, y..y+1)` のラッパー
145    pub fn get(&mut self, x: I, y: I) -> M::Val {
146        assert!(self.xmin <= x && x < self.xmax);
147        assert!(self.ymin <= y && y < self.ymax);
148        let one = I::one();
149        self.get_range(x..(x + one), y..(y + one))
150    }
151
152    // ---------- range parsing ----------
153
154    #[inline]
155    fn parse_range<R: RangeBounds<I>>(range: &R, min: I, max: I) -> Option<Range<I>> {
156        let start = match range.start_bound() {
157            Unbounded => min,
158            Excluded(&v) => v + I::one(),
159            Included(&v) => v,
160        };
161        let end = match range.end_bound() {
162            Unbounded => max,
163            Excluded(&v) => v,
164            Included(&v) => v + I::one(),
165        };
166        if min <= start && start <= end && end <= max {
167            Some((start, end))
168        } else {
169            None
170        }
171    }
172
173    #[inline]
174    fn parse_range_x<R: RangeBounds<I>>(&self, range: &R) -> Option<Range<I>> {
175        Self::parse_range(range, self.xmin, self.xmax)
176    }
177
178    #[inline]
179    fn parse_range_y<R: RangeBounds<I>>(&self, range: &R) -> Option<Range<I>> {
180        Self::parse_range(range, self.ymin, self.ymax)
181    }
182
183    // ---------- math helpers ----------
184
185    #[inline]
186    fn two() -> I {
187        I::one() + I::one()
188    }
189
190    #[inline]
191    fn mid(l: I, r: I) -> I {
192        l + (r - l) / Self::two()
193    }
194
195    #[inline]
196    fn len(l: I, r: I) -> usize {
197        (r - l).to_usize().unwrap()
198    }
199
200    #[inline]
201    fn area(((xl, xr), (yl, yr)): Rect<I>) -> usize {
202        Self::len(xl, xr) * Self::len(yl, yr)
203    }
204
205    #[inline]
206    fn is_leaf(((xl, xr), (yl, yr)): Rect<I>) -> bool {
207        xr - xl == I::one() && yr - yl == I::one()
208    }
209
210    #[inline]
211    fn intersects(((xl, xr), (yl, yr)): Rect<I>, ((qxl, qxr), (qyl, qyr)): Rect<I>) -> bool {
212        !(qxr <= xl || xr <= qxl || qyr <= yl || yr <= qyl)
213    }
214
215    #[inline]
216    fn covered_by(((xl, xr), (yl, yr)): Rect<I>, ((qxl, qxr), (qyl, qyr)): Rect<I>) -> bool {
217        qxl <= xl && xr <= qxr && qyl <= yl && yr <= qyr
218    }
219
220    #[inline]
221    fn can_split(axis: Axis, ((xl, xr), (yl, yr)): Rect<I>) -> bool {
222        match axis {
223            Axis::X => xr - xl > I::one(),
224            Axis::Y => yr - yl > I::one(),
225        }
226    }
227
228    // ---------- node helpers ----------
229
230    #[inline]
231    fn apply_node(&mut self, ptr: Ptr, act: &M::Act) {
232        let nsum = {
233            let v = self.arena.get(ptr);
234            M::mapping(&v.sum, act)
235        };
236        let nact = {
237            let v = self.arena.get(ptr);
238            M::compose(&v.act, act)
239        };
240        let v = self.arena.get_mut(ptr);
241        v.sum = nsum;
242        v.act = nact;
243    }
244
245    #[inline]
246    fn ensure_left(&mut self, ptr: Ptr, area: usize) -> Ptr {
247        if let Some(lp) = self.arena.get(ptr).left {
248            lp
249        } else {
250            let lp = self.arena.alloc(NodeInner::<M>::with_area(area));
251            self.arena.get_mut(ptr).left = Some(lp);
252            lp
253        }
254    }
255
256    #[inline]
257    fn ensure_right(&mut self, ptr: Ptr, area: usize) -> Ptr {
258        if let Some(rp) = self.arena.get(ptr).right {
259            rp
260        } else {
261            let rp = self.arena.alloc(NodeInner::<M>::with_area(area));
262            self.arena.get_mut(ptr).right = Some(rp);
263            rp
264        }
265    }
266
267    // ---------- split decision(固定) ----------
268
269    /// 未決定ノードに対してのみ呼ぶこと.決めたら `split_axis` に保存する.
270    ///
271    /// 優先順位:
272    /// 1) クエリがその軸で部分被覆ならその軸(境界を跨ぐ軸を先に潰す)
273    /// 2) それ以外は長い方
274    /// 3) tie は `axis_hint`
275    /// 4) split 不能なら反転して試す
276    fn decide_split_axis(&self, axis_hint: Axis, node_rect: Rect<I>, query: Rect<I>) -> Axis {
277        let ((xl, xr), (yl, yr)) = node_rect;
278        let ((qxl, qxr), (qyl, qyr)) = query;
279
280        let x_can = Self::can_split(Axis::X, node_rect);
281        let y_can = Self::can_split(Axis::Y, node_rect);
282
283        if !x_can && !y_can {
284            return axis_hint;
285        }
286        if x_can && !y_can {
287            return Axis::X;
288        }
289        if y_can && !x_can {
290            return Axis::Y;
291        }
292
293        // 交差している前提だが,軸方向の交差も念のため見る
294        let x_intersects = !(qxr <= xl || xr <= qxl);
295        let y_intersects = !(qyr <= yl || yr <= qyl);
296
297        let x_full = qxl <= xl && xr <= qxr;
298        let y_full = qyl <= yl && yr <= qyr;
299
300        let x_partial = x_intersects && !x_full;
301        let y_partial = y_intersects && !y_full;
302
303        if x_partial {
304            return Axis::X;
305        }
306        if y_partial {
307            return Axis::Y;
308        }
309
310        // 長い方
311        let x_len = xr - xl;
312        let y_len = yr - yl;
313        if x_len > y_len {
314            return Axis::X;
315        }
316        if y_len > x_len {
317            return Axis::Y;
318        }
319
320        // tie
321        axis_hint
322    }
323
324    /// ノード `ptr` の split 軸を確定して返す(既にあればそれを返す).
325    fn ensure_split_axis(
326        &mut self,
327        ptr: Ptr,
328        node_rect: Rect<I>,
329        query: Rect<I>,
330        hint: Axis,
331    ) -> Axis {
332        if let Some(ax) = self.arena.get(ptr).split_axis {
333            return ax;
334        }
335        let ax = self.decide_split_axis(hint, node_rect, query);
336        self.arena.get_mut(ptr).split_axis = Some(ax);
337        ax
338    }
339
340    /// split 軸が与えられたときの子領域を返す.
341    fn child_regions(
342        &self,
343        axis: Axis,
344        ((xl, xr), (yl, yr)): Rect<I>,
345    ) -> (Rect<I>, usize, Rect<I>, usize) {
346        match axis {
347            Axis::X => {
348                let xm = Self::mid(xl, xr);
349                let r1 = ((xl, xm), (yl, yr));
350                let r2 = ((xm, xr), (yl, yr));
351                (r1, Self::area(r1), r2, Self::area(r2))
352            }
353            Axis::Y => {
354                let ym = Self::mid(yl, yr);
355                let r1 = ((xl, xr), (yl, ym));
356                let r2 = ((xl, xr), (ym, yr));
357                (r1, Self::area(r1), r2, Self::area(r2))
358            }
359        }
360    }
361
362    // ---------- lazy propagation ----------
363
364    /// 遅延を子へ伝播(split 軸はノードに保存済みのものを使用)
365    fn push(&mut self, ptr: Ptr, node_rect: Rect<I>) {
366        if Self::is_leaf(node_rect) {
367            return;
368        }
369        let act = { self.arena.get(ptr).act.clone() };
370        if act == M::id() {
371            return;
372        }
373
374        // クエリ非依存に push したいので,split 軸は「既に決まっている」前提にする
375        // 未決定の可能性があるなら,ここで「領域だけ」で決める fallback を入れる
376        let axis = self.arena.get(ptr).split_axis.unwrap_or_else(|| {
377            // 領域だけで決める(tie は X)
378            let ((xl, xr), (yl, yr)) = node_rect;
379            let x_can = xr - xl > I::one();
380            let y_can = yr - yl > I::one();
381            if x_can && !y_can {
382                Axis::X
383            } else if y_can && !x_can {
384                Axis::Y
385            } else {
386                let x_len = xr - xl;
387                let y_len = yr - yl;
388                if x_len >= y_len {
389                    Axis::X
390                } else {
391                    Axis::Y
392                }
393            }
394        });
395
396        let (r1, a1, r2, a2) = self.child_regions(axis, node_rect);
397
398        let lp = self.ensure_left(ptr, a1);
399        let rp = self.ensure_right(ptr, a2);
400
401        self.apply_node(lp, &act);
402        self.apply_node(rp, &act);
403
404        self.arena.get_mut(ptr).act = M::id();
405
406        // push の時点で split 軸が未決定だったなら,ここで固定しておく(以後の一貫性のため)
407        if self.arena.get(ptr).split_axis.is_none() {
408            self.arena.get_mut(ptr).split_axis = Some(axis);
409        }
410
411        let _ = (r1, r2); // 参照用
412    }
413
414    fn pull(&mut self, ptr: Ptr, node_rect: Rect<I>) {
415        if Self::is_leaf(node_rect) {
416            return;
417        }
418        let axis = self.arena.get(ptr).split_axis.unwrap_or_else(|| {
419            // `push` と同じ fallback(理想は必ず Some になっていること)
420            let ((xl, xr), (yl, yr)) = node_rect;
421            let x_can = xr - xl > I::one();
422            let y_can = yr - yl > I::one();
423            if x_can && !y_can {
424                Axis::X
425            } else if y_can && !x_can {
426                Axis::Y
427            } else {
428                let x_len = xr - xl;
429                let y_len = yr - yl;
430                if x_len >= y_len {
431                    Axis::X
432                } else {
433                    Axis::Y
434                }
435            }
436        });
437
438        let (r1, a1, r2, a2) = self.child_regions(axis, node_rect);
439
440        let lp = self.arena.get(ptr).left;
441        let rp = self.arena.get(ptr).right;
442
443        let lsum = lp
444            .map(|p| self.arena.get(p).sum.clone())
445            .unwrap_or_else(|| M::e_with_size(a1));
446        let rsum = rp
447            .map(|p| self.arena.get(p).sum.clone())
448            .unwrap_or_else(|| M::e_with_size(a2));
449
450        self.arena.get_mut(ptr).sum = M::op(&lsum, &rsum);
451
452        // 念のため固定
453        if self.arena.get(ptr).split_axis.is_none() {
454            self.arena.get_mut(ptr).split_axis = Some(axis);
455        }
456
457        let _ = (r1, r2);
458    }
459
460    // ---------- recursions ----------
461
462    fn apply_inner(
463        &mut self,
464        node: Option<Ptr>,
465        node_rect: Rect<I>,
466        query: Rect<I>,
467        act: &M::Act,
468        axis_hint: Axis,
469    ) -> Option<Ptr> {
470        if !Self::intersects(node_rect, query) {
471            return node;
472        }
473
474        let area = Self::area(node_rect);
475        let ptr = node.unwrap_or_else(|| self.arena.alloc(NodeInner::<M>::with_area(area)));
476
477        if Self::covered_by(node_rect, query) {
478            self.apply_node(ptr, act);
479            return Some(ptr);
480        }
481
482        if Self::is_leaf(node_rect) {
483            self.apply_node(ptr, act);
484            return Some(ptr);
485        }
486
487        // 子へ遅延伝播(split 軸は固定されたものを使う)
488        self.push(ptr, node_rect);
489
490        // split 軸の確定(未決定なら,このクエリと hint を使って決めて固定)
491        let axis = self.ensure_split_axis(ptr, node_rect, query, axis_hint);
492
493        let (r1, a1, r2, a2) = self.child_regions(axis, node_rect);
494
495        let left = self.arena.get(ptr).left;
496        let nl = self.apply_inner(left, r1, query, act, axis.flip());
497        self.arena.get_mut(ptr).left = nl;
498
499        let right = self.arena.get(ptr).right;
500        let nr = self.apply_inner(right, r2, query, act, axis.flip());
501        self.arena.get_mut(ptr).right = nr;
502
503        // 吸い上げ
504        self.pull(ptr, node_rect);
505
506        let _ = (a1, a2);
507        Some(ptr)
508    }
509
510    fn get_range_inner(
511        &mut self,
512        node: Option<Ptr>,
513        node_rect: Rect<I>,
514        query: Rect<I>,
515        axis_hint: Axis,
516    ) -> M::Val {
517        if !Self::intersects(node_rect, query) {
518            return M::e_with_size(0);
519        }
520
521        let area = Self::area(node_rect);
522        if Self::covered_by(node_rect, query) {
523            return node
524                .map(|p| self.arena.get(p).sum.clone())
525                .unwrap_or_else(|| M::e_with_size(area));
526        }
527
528        if Self::is_leaf(node_rect) {
529            return node
530                .map(|p| self.arena.get(p).sum.clone())
531                .unwrap_or_else(|| M::e_with_size(area));
532        }
533
534        let Some(ptr) = node else {
535            // 一般の `ActedMonoidWithSize` に対して安全にするため,
536            // `None` でも分割して `op` で合成する(面積だけで即返ししない)
537            let axis = self.decide_split_axis(axis_hint, node_rect, query);
538            let (r1, _a1, r2, _a2) = self.child_regions(axis, node_rect);
539
540            let a = self.get_range_inner(None, r1, query, axis.flip());
541            let b = self.get_range_inner(None, r2, query, axis.flip());
542            return M::op(&a, &b);
543        };
544
545        self.push(ptr, node_rect);
546
547        let axis = self.ensure_split_axis(ptr, node_rect, query, axis_hint);
548        let (r1, _a1, r2, _a2) = self.child_regions(axis, node_rect);
549
550        let a = self.get_range_inner(self.arena.get(ptr).left, r1, query, axis.flip());
551        let b = self.get_range_inner(self.arena.get(ptr).right, r2, query, axis.flip());
552        M::op(&a, &b)
553    }
554}