結果

問題 No.777 再帰的ケーキ
コンテスト
ユーザー urectanc
提出日時 2026-05-06 08:54:46
言語 Rust
(1.94.0 + proconio + num + itertools)
コンパイル:
/usr/bin/rustc_custom
実行:
./target/release/main
結果
AC  
実行時間 154 ms / 2,000 ms
コード長 8,151 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 2,808 ms
コンパイル使用メモリ 226,220 KB
実行使用メモリ 15,660 KB
最終ジャッジ日時 2026-05-06 08:54:58
合計ジャッジ時間 7,363 ms
ジャッジサーバーID
(参考情報)
judge1_0 / judge3_0
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 4
other AC * 33
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

use std::collections::HashMap;

use itertools::Itertools;
use proconio::input;
use urectanc::{algebra::Monoid, segment_tree::SegmentTree};

fn main() {
    input! {
        n: usize,
        mut abc: [(u32, u32, u64); n],
    }

    abc.sort_unstable();
    let values = abc
        .iter()
        .map(|t| t.1)
        .sorted_unstable()
        .dedup()
        .collect_vec();
    let compress = values
        .iter()
        .enumerate()
        .map(|(i, &x)| (x, i))
        .collect::<HashMap<_, _>>();

    let mut v = vec![0; values.len()];
    let mut seg = SegmentTree::<Max>::from(&v);
    let mut update = vec![];
    for chunk in abc.chunk_by(|x, y| x.0 == y.0) {
        for &(_, b, c) in chunk {
            let b = compress[&b];
            let cand = seg.prod(..b) + c;
            if v[b] < cand {
                update.push((b, cand));
            }
        }
        for (b, cand) in update.drain(..) {
            if v[b] < cand {
                v[b] = cand;
                seg.set(b, cand);
            }
        }
    }

    let ans = seg.prod(..);
    println!("{ans}");
}

struct Max;

impl Monoid for Max {
    type Elem = u64;

    fn identity() -> Self::Elem {
        0
    }

    fn op(lhs: &Self::Elem, rhs: &Self::Elem) -> Self::Elem {
        *(lhs.max(rhs))
    }
}


pub mod urectanc {
    pub mod algebra {
        pub trait Monoid {
            type Elem: Clone;
            fn identity() -> Self::Elem;
            fn op(lhs: &Self::Elem, rhs: &Self::Elem) -> Self::Elem;
        }
        pub trait Group: Monoid {
            fn inv(elem: &Self::Elem) -> Self::Elem;
        }
        pub trait MapMonoid: Monoid {
            type Map: Clone;
            fn identity_map() -> Self::Map;
            fn apply(x: &Self::Elem, f: &Self::Map) -> Self::Elem;
            fn compose(f: &Self::Map, g: &Self::Map) -> Self::Map;
        }
        pub struct Reverse<M> {
            _phantom: std::marker::PhantomData<M>,
        }
        impl<M: Monoid> Monoid for Reverse<M> {
            type Elem = M::Elem;
            fn identity() -> Self::Elem {
                M::identity()
            }
            fn op(lhs: &Self::Elem, rhs: &Self::Elem) -> Self::Elem {
                M::op(rhs, lhs)
            }
        }
    }
    pub mod segment_tree {
        use crate::urectanc::{algebra, clamp_range};
        use std::ops::RangeBounds;
        use algebra::Monoid;
        use clamp_range::ClampRange;
        pub struct SegmentTree<M: Monoid> {
            len: usize,
            offset: usize,
            tree: Vec<M::Elem>,
        }
        impl<M: Monoid> SegmentTree<M> {
            pub fn new(len: usize) -> Self {
                let offset = len.next_power_of_two();
                let tree = vec![M::identity(); 2 * offset];
                Self { len, offset, tree }
            }
            pub fn to_vec(&self) -> Vec<M::Elem> {
                self.tree[self.offset..][..self.len].to_vec()
            }
            pub fn get(&self, i: usize) -> M::Elem {
                self.tree[i + self.offset].clone()
            }
            pub fn set(&mut self, mut i: usize, val: M::Elem) {
                i += self.offset;
                self.tree[i] = val;
                while i > 1 {
                    i >>= 1;
                    self.update(i);
                }
            }
            pub fn prod(&self, range: impl RangeBounds<usize>) -> M::Elem {
                let (mut l, mut r) = range.clamp(0, self.len);
                if (l, r) == (0, self.len) {
                    return self.tree[1].clone();
                }
                (l, r) = (l + self.offset, r + self.offset);
                let mut acc_l = M::identity();
                let mut acc_r = M::identity();
                while l < r {
                    if l & 1 == 1 {
                        acc_l = M::op(&acc_l, &self.tree[l]);
                        l += 1;
                    }
                    if r & 1 == 1 {
                        r -= 1;
                        acc_r = M::op(&self.tree[r], &acc_r);
                    }
                    (l, r) = (l >> 1, r >> 1);
                }
                M::op(&acc_l, &acc_r)
            }
            pub fn max_right(&self, l: usize, f: impl Fn(&M::Elem) -> bool) -> usize {
                let mut r = l;
                let (mut i, mut width) = (r + self.offset, 1);
                let mut acc = M::identity();
                assert!(f(& acc));
                while r + width <= self.len {
                    if i & 1 == 1 {
                        let next_acc = M::op(&acc, &self.tree[i]);
                        if !f(&next_acc) {
                            break;
                        }
                        acc = next_acc;
                        (r, i) = (r + width, i + 1);
                    }
                    (i, width) = (i >> 1, width << 1);
                }
                while width > 1 {
                    (i, width) = (i << 1, width >> 1);
                    if r + width <= self.len {
                        let next_acc = M::op(&acc, &self.tree[i]);
                        if f(&next_acc) {
                            acc = next_acc;
                            (r, i) = (r + width, i + 1);
                        }
                    }
                }
                r
            }
            pub fn min_left(&self, r: usize, f: impl Fn(&M::Elem) -> bool) -> usize {
                let mut l = r;
                let (mut i, mut width) = (l + self.offset, 1);
                let mut acc = M::identity();
                assert!(f(& acc));
                while l >= width {
                    if i & 1 == 1 {
                        let next_acc = M::op(&self.tree[i - 1], &acc);
                        if !f(&next_acc) {
                            break;
                        }
                        acc = next_acc;
                        (l, i) = (l - width, i - 1);
                    }
                    (i, width) = (i >> 1, width << 1);
                }
                while width > 1 {
                    (i, width) = (i << 1, width >> 1);
                    if l >= width {
                        let next_acc = M::op(&self.tree[i - 1], &acc);
                        if f(&next_acc) {
                            acc = next_acc;
                            (l, i) = (l - width, i - 1);
                        }
                    }
                }
                l
            }
            fn update(&mut self, i: usize) {
                self.tree[i] = M::op(&self.tree[2 * i], &self.tree[2 * i + 1]);
            }
        }
        impl<M, T> From<T> for SegmentTree<M>
        where
            M: Monoid,
            T: AsRef<[M::Elem]>,
        {
            fn from(value: T) -> Self {
                let a = value.as_ref();
                let len = a.len();
                let offset = len.next_power_of_two();
                let mut tree = vec![M::identity(); 2 * offset];
                tree[offset..][..len].clone_from_slice(a);
                let mut segtree = Self { len, offset, tree };
                for i in (1..offset).rev() {
                    segtree.update(i);
                }
                segtree
            }
        }
    }
    pub mod clamp_range {
        use std::ops::{Bound, RangeBounds};
        pub trait ClampRange: RangeBounds<usize> {
            fn clamp(&self, l: usize, r: usize) -> (usize, usize) {
                assert!(l <= r);
                let start = match self.start_bound() {
                    Bound::Included(&l) => l,
                    Bound::Excluded(&l) => l + 1,
                    Bound::Unbounded => l,
                }
                    .clamp(l, r);
                let end = match self.end_bound() {
                    Bound::Included(&r) => r + 1,
                    Bound::Excluded(&r) => r,
                    Bound::Unbounded => r,
                }
                    .clamp(l, r);
                (start.min(end), end)
            }
        }
        impl<T: ?Sized> ClampRange for T
        where
            T: RangeBounds<usize>,
        {}
    }
}
0