procon_lib_rs

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub CoCo-Japan-pan/procon_lib_rs

:heavy_check_mark: crates/misc/mo/src/lib.rs

Required by

Verified with

Code

//! [Mo's algorithm](https://ei1333.hateblo.jp/entry/2017/09/11/211011)  
//! 一般に二つのindex `(x, y)` をとるクエリ達に対して、`x`や`y`を+-1する変更を`O(α)`でできる場合  
//! `0 <= x <= nx, 0 <= y <= ny` とすると全体で`O(α\sqrt{nxnyQ})`で処理できる (Q = クエリの数)  
//! クエリ先読みが必要  
//! index`(x, y)`が区間クエリ`[x, y)`に対応する場合がよくある使い方だが、
//! 別に`x <= y`である必要はなく、一般に二つのindexをとるクエリ全般に使える

/// 現在のクエリの値、indexの+-1の変更、答えの配列を管理するtrait  
/// クエリ(0, 0)で初期化する
pub trait MoFuncs {
    /// (x, y) -> (x-1, y) の変更
    fn x_minus(&mut self, x: usize);
    /// (x, y) -> (x+1, y) の変更
    fn x_plus(&mut self, x: usize);
    /// (x, y) -> (x, y-1) の変更
    fn y_minus(&mut self, y: usize);
    /// (x, y) -> (x, y+1) の変更
    fn y_plus(&mut self, y: usize);
    /// 現在のクエリの値を、答えの配列のidx番目に記録する
    fn memo(&mut self, idx: usize);
}

#[derive(Debug)]
pub struct MoRunner<'a> {
    querys: &'a [(usize, usize)],
    order: Vec<usize>,
}

impl<'a> MoRunner<'a> {
    /// `querys` はオフラインで読み込んだクエリ(x, y) の配列  
    /// `0 <= x <= nx, 0 <= y <= ny` とする
    pub fn new(querys: &'a [(usize, usize)], nx: usize, ny: usize) -> Self {
        let order = calc_mo_friendly_order(querys, nx, ny);
        Self { querys, order }
    }

    /// クエリ(0, 0)から初めて、indexの+-1の変更を行いすべてのクエリを処理する  
    /// クエリの値を順に保持した配列を返す
    pub fn run<M: MoFuncs>(&self, mo_funcs: &mut M) {
        let mut x = 0;
        let mut y = 0;
        for id in &self.order {
            let (nx, ny) = self.querys[*id];
            while x > nx {
                mo_funcs.x_minus(x);
                x -= 1;
            }
            while y < ny {
                mo_funcs.y_plus(y);
                y += 1;
            }
            while x < nx {
                mo_funcs.x_plus(x);
                x += 1;
            }
            while y > ny {
                mo_funcs.y_minus(y);
                y -= 1;
            }
            mo_funcs.memo(*id);
        }
    }
}

/// クエリの左右端+-1変化が少なくなるように、クエリ番号[0,1,...Q)をソートした配列を返す  
/// 各クエリ`(x, y)`は、`0 <= x <= nx, 0 <= y <= ny` とする
pub fn calc_mo_friendly_order(query_ranges: &[(usize, usize)], nx: usize, ny: usize) -> Vec<usize> {
    if query_ranges.is_empty() {
        return vec![];
    }
    let query_cnt = query_ranges.len();
    let mut order = (0..query_cnt).collect::<Vec<_>>();
    let block_size = ((nx as f64 * ny as f64 / query_cnt as f64).sqrt().ceil() as usize).max(1);
    // x/block_sizeでソート その中ではyでソート yについては昇順と降順を交互にする
    order.sort_unstable_by(|&a, &b| {
        let (x1, y1) = query_ranges[a];
        let (x2, y2) = query_ranges[b];
        let block1 = x1 / block_size;
        let block2 = x2 / block_size;
        block1.cmp(&block2).then(if (block1 & 1) == 0 {
            y1.cmp(&y2)
        } else {
            y2.cmp(&y1)
        })
    });
    order
}
Traceback (most recent call last):
  File "/opt/hostedtoolcache/Python/3.13.9/x64/lib/python3.13/site-packages/onlinejudge_verify/documentation/build.py", line 71, in _render_source_code_stat
    bundled_code = language.bundle(stat.path, basedir=basedir, options={'include_paths': [basedir]}).decode()
                   ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.13.9/x64/lib/python3.13/site-packages/onlinejudge_verify/languages/rust.py", line 288, in bundle
    raise NotImplementedError
NotImplementedError
Back to top page