結果

問題 No.3671 Reusable Lazy Segment Tree
コンテスト
ユーザー harurun
提出日時 2026-08-15 11:55:27
言語 Rust
(1.97.1 + proconio + num + itertools + ACL)
コンパイル:
/usr/bin/rustc_custom
実行:
./target/release/main
結果
AC  
実行時間 4,440 ms / 6,000 ms
+ 52µs
コード長 12,125 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 8,933 ms
コンパイル使用メモリ 190,712 KB
実行使用メモリ 46,592 KB
最終ジャッジ日時 2026-09-04 22:27:01
合計ジャッジ時間 40,347 ms
ジャッジサーバーID
(参考情報)
judge1_0 / judge3_0
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 1
other AC * 19
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

use std::fmt::Write as _;
use std::io::{self, Read};

const BITS: usize = 30;
const VALUE_MASK: u32 = (1u32 << BITS) - 1;

#[derive(Clone, Copy)]
struct Node {
    sum: u64,
    cnt: [u32; BITS],
    any: u32,
    all: u32,
    lazy_and: u32,
    lazy_or: u32,
}

impl Node {
    fn new() -> Self {
        Self {
            sum: 0,
            cnt: [0; BITS],
            any: 0,
            all: 0,
            lazy_and: VALUE_MASK,
            lazy_or: 0,
        }
    }
}

struct RollbackLazySegTree {
    n: usize,
    size: usize,
    tree: Vec<Node>,

    // A node is copied at most once in each subproblem.
    saved_epoch: Vec<usize>,
    epoch: usize,
    history: Vec<(usize, Node)>,
}

impl RollbackLazySegTree {
    fn new(a: &[u32]) -> Self {
        let n = a.len();
        let mut size = 1usize;

        while size < n {
            size <<= 1;
        }

        let mut seg = Self {
            n,
            size,
            tree: vec![Node::new(); size << 1],
            saved_epoch: vec![0; size << 1],
            epoch: 0,
            history: Vec::with_capacity(4096),
        };

        seg.build(1, 0, size - 1, a);
        seg
    }

    #[inline]
    fn contribution(count: u32, bit: usize) -> u64 {
        (count as u64) << bit
    }

    #[inline]
    fn save(&mut self, p: usize) {
        if self.saved_epoch[p] == self.epoch {
            return;
        }

        self.saved_epoch[p] = self.epoch;
        self.history.push((p, self.tree[p]));
    }

    fn build(
        &mut self,
        p: usize,
        l: usize,
        r: usize,
        a: &[u32],
    ) {
        self.tree[p] = Node::new();

        if l == r {
            let value = if l < self.n {
                a[l]
            } else {
                0
            };

            let cur = &mut self.tree[p];

            cur.sum = value as u64;
            cur.any = value;
            cur.all = value;

            for b in 0..BITS {
                cur.cnt[b] = (value >> b) & 1;
            }

            return;
        }

        let mid = (l + r) >> 1;

        self.build(p << 1, l, mid, a);
        self.build(p << 1 | 1, mid + 1, r, a);

        let left = self.tree[p << 1];
        let right = self.tree[p << 1 | 1];

        let cur = &mut self.tree[p];

        cur.sum = left.sum + right.sum;
        cur.any = left.any | right.any;
        cur.all = left.all & right.all;

        for b in 0..BITS {
            cur.cnt[b] = left.cnt[b] + right.cnt[b];
        }
    }

    fn apply_or(
        &mut self,
        p: usize,
        len: usize,
        mask: u32,
    ) -> u32 {
        let changed = mask & !self.tree[p].all;

        if changed == 0 {
            return 0;
        }

        self.save(p);

        let cur = &mut self.tree[p];
        let mut bits = changed;

        while bits != 0 {
            let b = bits.trailing_zeros() as usize;
            bits &= bits - 1;

            let old_count = cur.cnt[b];
            let new_count = len as u32;

            cur.sum += Self::contribution(new_count - old_count, b);
            cur.cnt[b] = new_count;
        }

        cur.any |= mask;
        cur.all |= mask;
        cur.lazy_or |= mask;

        changed
    }

    fn apply_and(
        &mut self,
        p: usize,
        mask: u32,
    ) -> u32 {
        let changed = self.tree[p].any & !mask;

        if changed == 0 {
            return 0;
        }

        self.save(p);

        let cur = &mut self.tree[p];
        let mut bits = changed;

        while bits != 0 {
            let b = bits.trailing_zeros() as usize;
            bits &= bits - 1;

            let old_count = cur.cnt[b];

            cur.sum -= Self::contribution(old_count, b);
            cur.cnt[b] = 0;
        }

        cur.any &= mask;
        cur.all &= mask;
        cur.lazy_and &= mask;
        cur.lazy_or &= mask;

        changed
    }

    fn push(
        &mut self,
        p: usize,
        l: usize,
        r: usize,
    ) {
        let lazy_and = self.tree[p].lazy_and;
        let lazy_or = self.tree[p].lazy_or;

        if l == r || (lazy_and == VALUE_MASK && lazy_or == 0) {
            return;
        }

        let mid = (l + r) >> 1;
        let left_len = mid - l + 1;
        let right_len = r - mid;

        self.apply_and(p << 1, lazy_and);
        self.apply_or(p << 1, left_len, lazy_or);

        self.apply_and(p << 1 | 1, lazy_and);
        self.apply_or(p << 1 | 1, right_len, lazy_or);

        self.save(p);

        self.tree[p].lazy_and = VALUE_MASK;
        self.tree[p].lazy_or = 0;
    }

    fn pull_changed(
        &mut self,
        p: usize,
        len: usize,
        changed: u32,
    ) {
        if changed == 0 {
            return;
        }

        self.save(p);

        let left = self.tree[p << 1];
        let right = self.tree[p << 1 | 1];

        let cur = &mut self.tree[p];

        let mut bits = changed;

        while bits != 0 {
            let b = bits.trailing_zeros() as usize;
            bits &= bits - 1;

            let bit_mask = 1u32 << b;

            let old_count = cur.cnt[b];
            let new_count = left.cnt[b] + right.cnt[b];

            if new_count > old_count {
                cur.sum +=
                    Self::contribution(new_count - old_count, b);
            } else {
                cur.sum -=
                    Self::contribution(old_count - new_count, b);
            }

            cur.cnt[b] = new_count;

            if new_count == 0 {
                cur.any &= !bit_mask;
            } else {
                cur.any |= bit_mask;
            }

            if new_count == len as u32 {
                cur.all |= bit_mask;
            } else {
                cur.all &= !bit_mask;
            }
        }
    }

    fn range_or_impl(
        &mut self,
        p: usize,
        l: usize,
        r: usize,
        ql: usize,
        qr: usize,
        mask: u32,
    ) -> u32 {
        if qr < l || r < ql {
            return 0;
        }

        if (mask & !self.tree[p].all) == 0 {
            return 0;
        }

        if ql <= l && r <= qr {
            return self.apply_or(
                p,
                r - l + 1,
                mask,
            );
        }

        self.push(p, l, r);

        let mid = (l + r) >> 1;

        let changed_left = self.range_or_impl(
            p << 1,
            l,
            mid,
            ql,
            qr,
            mask,
        );

        let changed_right = self.range_or_impl(
            p << 1 | 1,
            mid + 1,
            r,
            ql,
            qr,
            mask,
        );

        let changed = changed_left | changed_right;

        self.pull_changed(
            p,
            r - l + 1,
            changed,
        );

        changed
    }

    fn range_and_impl(
        &mut self,
        p: usize,
        l: usize,
        r: usize,
        ql: usize,
        qr: usize,
        mask: u32,
    ) -> u32 {
        if qr < l || r < ql {
            return 0;
        }

        if (self.tree[p].any & !mask) == 0 {
            return 0;
        }

        if ql <= l && r <= qr {
            return self.apply_and(p, mask);
        }

        self.push(p, l, r);

        let mid = (l + r) >> 1;

        let changed_left = self.range_and_impl(
            p << 1,
            l,
            mid,
            ql,
            qr,
            mask,
        );

        let changed_right = self.range_and_impl(
            p << 1 | 1,
            mid + 1,
            r,
            ql,
            qr,
            mask,
        );

        let changed = changed_left | changed_right;

        self.pull_changed(
            p,
            r - l + 1,
            changed,
        );

        changed
    }

    fn range_sum_impl(
        &mut self,
        p: usize,
        l: usize,
        r: usize,
        ql: usize,
        qr: usize,
    ) -> u64 {
        if qr < l || r < ql {
            return 0;
        }

        if ql <= l && r <= qr {
            return self.tree[p].sum;
        }

        self.push(p, l, r);

        let mid = (l + r) >> 1;

        self.range_sum_impl(
            p << 1,
            l,
            mid,
            ql,
            qr,
        ) + self.range_sum_impl(
            p << 1 | 1,
            mid + 1,
            r,
            ql,
            qr,
        )
    }

    fn begin_subproblem(&mut self) {
        self.epoch += 1;
        self.history.clear();
    }

    fn rollback(&mut self) {
        for &(p, node) in self.history.iter().rev() {
            self.tree[p] = node;
        }

        self.history.clear();
    }

    fn range_or(
        &mut self,
        l: usize,
        r: usize,
        mask: u32,
    ) {
        self.range_or_impl(
            1,
            0,
            self.size - 1,
            l,
            r,
            mask,
        );
    }

    fn range_and(
        &mut self,
        l: usize,
        r: usize,
        mask: u32,
    ) {
        self.range_and_impl(
            1,
            0,
            self.size - 1,
            l,
            r,
            mask,
        );
    }

    fn range_sum(
        &mut self,
        l: usize,
        r: usize,
    ) -> u64 {
        self.range_sum_impl(
            1,
            0,
            self.size - 1,
            l,
            r,
        )
    }
}

#[inline]
fn clamp_index(
    value: u32,
    n: usize,
) -> usize {
    if value < 1 {
        1
    } else if value > n as u32 {
        n
    } else {
        value as usize
    }
}

fn main() {
    let mut input = String::new();
    io::stdin()
        .read_to_string(&mut input)
        .unwrap();

    let mut it = input.split_whitespace();

    let n: usize =
        it.next().unwrap().parse().unwrap();
    let m: usize =
        it.next().unwrap().parse().unwrap();

    let mut a = vec![0u32; n];

    for value in &mut a {
        *value =
            it.next().unwrap().parse().unwrap();
    }

    let mut l = vec![0u32; m + 1];
    let mut r = vec![0u32; m + 1];
    let mut x = vec![0u32; m + 1];
    let mut big_l = vec![0u32; m + 1];
    let mut big_r = vec![0u32; m + 1];

    for i in 1..=m {
        l[i] =
            it.next().unwrap().parse().unwrap();
    }

    for i in 1..=m {
        r[i] =
            it.next().unwrap().parse().unwrap();
    }

    for i in 1..=m {
        x[i] =
            it.next().unwrap().parse().unwrap();
    }

    for i in 1..=m {
        big_l[i] =
            it.next().unwrap().parse().unwrap();
    }

    for i in 1..=m {
        big_r[i] =
            it.next().unwrap().parse().unwrap();
    }

    let mut seg =
        RollbackLazySegTree::new(&a);

    let q_count: usize =
        it.next().unwrap().parse().unwrap();

    let mut output = String::new();

    for i in 1..=q_count {
        let s: usize =
            it.next().unwrap().parse().unwrap();

        let q: usize =
            it.next().unwrap().parse().unwrap();

        seg.begin_subproblem();

        let mut y = i as u32;

        for j in 1..=q {
            let z = ((s + j) % m) + 1;

            let u =
                clamp_index(l[z] ^ y, n);
            let v =
                clamp_index(r[z] ^ y, n);

            let ql = u.min(v) - 1;
            let qr = u.max(v) - 1;

            let big_u =
                clamp_index(big_l[z] ^ y, n);
            let big_v =
                clamp_index(big_r[z] ^ y, n);

            let sum_l =
                big_u.min(big_v) - 1;
            let sum_r =
                big_u.max(big_v) - 1;

            let mask = x[z] ^ y;

            if (z & 1) == 0 {
                seg.range_or(
                    ql,
                    qr,
                    mask,
                );
            } else {
                seg.range_and(
                    ql,
                    qr,
                    mask,
                );
            }

            y =
                (seg.range_sum(sum_l, sum_r) as u32)
                    & VALUE_MASK;
        }

        writeln!(&mut output, "{}", y).unwrap();

        seg.rollback();
    }

    print!("{}", output);
}
0