結果

問題 No.3423 Minimum Xor Query
コンテスト
ユーザー urectanc
提出日時 2026-02-24 20:42:22
言語 Rust
(1.93.0 + proconio + num + itertools)
コンパイル:
/usr/bin/rustc_custom
実行:
./target/release/main
結果
AC  
実行時間 3,572 ms / 5,000 ms
コード長 6,396 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 3,172 ms
コンパイル使用メモリ 230,392 KB
実行使用メモリ 7,844 KB
最終ジャッジ日時 2026-02-24 20:43:10
合計ジャッジ時間 33,231 ms
ジャッジサーバーID
(参考情報)
judge4 / judge1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 18
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

use itertools::Itertools;
use proconio::{fastout, input, marker::Usize1};

use crate::multiset::MultiSet;

#[fastout]
fn main() {
    input! {
        n: usize, q: usize,
        a: [u32; n],
    }

    let mut update = vec![];
    let mut mo_queries = vec![];
    {
        let mut a = a.clone();
        for _ in 0..q {
            input! { op: u8 }
            if op == 1 {
                input! { i: Usize1, x: u32 }
                update.push((i, a[i], x));
                a[i] = x;
            } else {
                input! { r: usize }
                mo_queries.push((update.len(), r));
            }
        }
    }

    let data = AdjXor {
        a,
        update,
        set: MultiSet::new(),
        xor: MultiSet::new(),
    };

    let ans = mo::solve(data, &mo_queries);
    println!("{}", ans.iter().join("\n"));
}

struct AdjXor {
    a: Vec<u32>,
    update: Vec<(usize, u32, u32)>,
    set: MultiSet,
    xor: MultiSet,
}

impl AdjXor {
    fn insert(&mut self, x: u32) {
        if self.set.count(x) > 0 {
            self.xor.insert(0);
        } else {
            match (self.set.prev(x), self.set.next(x)) {
                (None, None) => (),
                (None, Some(next)) => self.xor.insert(next ^ x),
                (Some(prev), None) => self.xor.insert(prev ^ x),
                (Some(prev), Some(next)) => {
                    self.xor.remove(prev ^ next);
                    self.xor.insert(prev ^ x);
                    self.xor.insert(next ^ x);
                }
            }
        }
        self.set.insert(x);
    }

    fn remove(&mut self, x: u32) {
        self.set.remove(x);
        if self.set.count(x) > 0 {
            self.xor.remove(0);
        } else {
            match (self.set.prev(x), self.set.next(x)) {
                (None, None) => (),
                (None, Some(next)) => self.xor.remove(next ^ x),
                (Some(prev), None) => self.xor.remove(prev ^ x),
                (Some(prev), Some(next)) => {
                    self.xor.insert(prev ^ next);
                    self.xor.remove(prev ^ x);
                    self.xor.remove(next ^ x);
                }
            }
        }
    }
}

impl mo::Mo for AdjXor {
    type Result = u32;

    fn increment_x(&mut self, x: usize) {
        let (i, old, new) = self.update[x];
        if i < self.set.len() {
            self.remove(old);
            self.insert(new);
        }
        self.a[i] = new;
    }

    fn decrement_x(&mut self, x: usize) {
        let (i, old, new) = self.update[x];
        if i < self.set.len() {
            self.remove(new);
            self.insert(old);
        }
        self.a[i] = old;
    }

    fn increment_y(&mut self, y: usize) {
        self.insert(self.a[y]);
    }

    fn decrement_y(&mut self, y: usize) {
        self.remove(self.a[y]);
    }

    fn query(&self) -> Self::Result {
        self.xor.first().unwrap()
    }
}

#[allow(unused)]
mod mo {
    pub trait Mo {
        type Result: Clone + Default;

        fn increment_x(&mut self, x: usize);
        fn decrement_x(&mut self, x: usize);
        fn increment_y(&mut self, y: usize);
        fn decrement_y(&mut self, y: usize);
        fn query(&self) -> Self::Result;
    }

    pub fn solve<M: Mo>(mut data: M, queries: &[(usize, usize)]) -> Vec<M::Result> {
        let q = queries.len();
        let x_max = queries.iter().map(|&(x, _)| x).max().unwrap() as f64;
        let y_max = queries.iter().map(|&(_, y)| y).max().unwrap() as f64;
        let is_segment = queries.iter().all(|&(x, y)| x <= y);

        let coeff = if is_segment { 2.0 } else { 1.0 } / 3.0;
        let bucket_num = (coeff * q as f64 * x_max / y_max).sqrt();
        let bucket_width = (x_max / bucket_num).ceil() as usize;

        let mut sorted = queries.into_iter().copied().enumerate().collect::<Vec<_>>();
        sorted.sort_unstable_by_key(|&(_, (x, y))| (x / bucket_width, y));
        sorted
            .chunk_by_mut(|&(_, (x0, _)), &(_, (x1, _))| x0 / bucket_width == x1 / bucket_width)
            .skip(1)
            .step_by(2)
            .for_each(|bucket| bucket.reverse());

        let mut ans = vec![M::Result::default(); q];
        let (mut x, mut y) = (0, 0);
        for (i, (qx, qy)) in sorted {
            while qx < x {
                x -= 1;
                data.decrement_x(x);
            }
            while y < qy {
                data.increment_y(y);
                y += 1;
            }
            while x < qx {
                data.increment_x(x);
                x += 1;
            }
            while qy < y {
                y -= 1;
                data.decrement_y(y);
            }

            ans[i] = data.query();
        }

        ans
    }
}

#[allow(unused)]
mod multiset {
    use std::collections::BTreeMap;

    pub struct MultiSet {
        len: usize,
        map: BTreeMap<u32, usize>,
    }

    impl std::fmt::Debug for MultiSet {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            f.debug_set()
                .entries(
                    self.map
                        .iter()
                        .flat_map(|(&k, &v)| std::iter::repeat_n(k, v)),
                )
                .finish()
        }
    }

    impl MultiSet {
        pub fn new() -> Self {
            Self {
                len: 0,
                map: BTreeMap::new(),
            }
        }

        pub fn len(&self) -> usize {
            self.len
        }

        pub fn insert(&mut self, x: u32) {
            self.len += 1;
            *self.map.entry(x).or_insert(0) += 1;
        }

        pub fn remove(&mut self, x: u32) {
            self.len -= 1;
            *self.map.get_mut(&x).unwrap() -= 1;
            if self.count(x) == 0 {
                self.map.remove(&x);
            }
        }

        pub fn count(&self, x: u32) -> usize {
            *self.map.get(&x).unwrap_or(&0)
        }

        pub fn prev(&self, x: u32) -> Option<u32> {
            self.map.range(..x).last().map(|(&k, _)| k)
        }

        pub fn next(&self, x: u32) -> Option<u32> {
            self.map.range(x + 1..).next().map(|(&k, _)| k)
        }

        pub fn first(&self) -> Option<u32> {
            self.map.first_key_value().map(|(&k, _)| k)
        }

        pub fn last(&self) -> Option<u32> {
            self.map.last_key_value().map(|(&k, _)| k)
        }
    }
}
0