結果

問題 No.749 クエリ全部盛り
ユーザー LyricalMaestro
提出日時 2025-05-24 20:10:03
言語 Rust
(1.83.0 + proconio)
結果
AC  
実行時間 986 ms / 3,000 ms
コード長 7,396 bytes
コンパイル時間 13,031 ms
コンパイル使用メモリ 398,064 KB
実行使用メモリ 231,972 KB
最終ジャッジ日時 2025-05-24 20:10:25
合計ジャッジ時間 16,870 ms
ジャッジサーバーID
(参考情報)
judge5 / judge3
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 20
権限があれば一括ダウンロードができます
コンパイルメッセージ
warning: variable does not need to be mutable
  --> src/main.rs:21:13
   |
21 |         let mut lazy_array = vec![UNIT_MATRIX; 2 * n];
   |             ----^^^^^^^^^^
   |             |
   |             help: remove this `mut`
   |
   = note: `#[warn(unused_mut)]` on by default

ソースコード

diff #

use std::io::{self, BufRead};
const MOD: i64 = 1_000_000_007;
const UNIT_MATRIX: [i64; 9] = [1, 0, 0, 0, 1, 0, 0, 0, 1];

struct LazySegmentTree {
    size: usize,
    array: Vec<[i64; 3]>,
    lazy_array: Vec<[i64; 9]>,
    tmp_matrix: [i64; 9],
    tmp_vector: [i64; 3],
}

impl LazySegmentTree {
    fn new(init_array: &[[i64; 3]]) -> Self {
        let mut n = 1;
        while n < init_array.len() {
            n *= 2;
        }

        let mut array = vec![[0; 3]; 2 * n];
        let mut lazy_array = vec![UNIT_MATRIX; 2 * n];

        for (i, &a) in init_array.iter().enumerate() {
            array[n + i] = a;
        }

        for i in (1..n).rev() {
            let left = array[2 * i];
            let right = array[2 * i + 1];
            let mut current = array[i];
            Self::op(&mut current, &left, &right);
            array[i] = current;
        }

        LazySegmentTree {
            size: n,
            array,
            lazy_array,
            tmp_matrix: [0; 9],
            tmp_vector: [0; 3],
        }
    }

    fn op(res: &mut [i64; 3], left: &[i64; 3], right: &[i64; 3]) {
        for i in 0..3 {
            res[i] = (left[i] + right[i]) % MOD;
        }
    }

    fn op2(&mut self, matrix: &[i64; 9], array: &mut [i64; 9]) {
        for i in 0..3 {
            for j in 0..3 {
                let mut y = 0;
                for k in 0..3 {
                    y = (y + matrix[i * 3 + k] * array[k * 3 + j]) % MOD;
                }
                self.tmp_matrix[i * 3 + j] = y;
            }
        }
        array.copy_from_slice(&self.tmp_matrix);
    }

    fn op3(&mut self, matrix: &[i64; 9], array: &mut [i64; 3]) {
        for i in 0..3 {
            let mut y = 0;
            for j in 0..3 {
                y = (y + matrix[i * 3 + j] * array[j]) % MOD;
            }
            self.tmp_vector[i] = y;
        }
        array.copy_from_slice(&self.tmp_vector);
    }

    fn is_unit_matrix(array: &[i64; 9]) -> bool {
        array == &UNIT_MATRIX
    }

    fn propagate(&mut self, i: usize) {
        if Self::is_unit_matrix(&self.lazy_array[i]) {
            return;
        }
        let v = self.lazy_array[i];
        if i < self.size {
            let mut left_lazy = self.lazy_array[2 * i];
            let mut right_lazy = self.lazy_array[2 * i + 1];
            self.op2(&v, &mut left_lazy);
            self.op2(&v, &mut right_lazy);
            self.lazy_array[2 * i] = left_lazy;
            self.lazy_array[2 * i + 1] = right_lazy;

            let mut left_array = self.array[2 * i];
            let mut right_array = self.array[2 * i + 1];
            self.op3(&v, &mut left_array);
            self.op3(&v, &mut right_array);
            self.array[2 * i] = left_array;
            self.array[2 * i + 1] = right_array;
        }
        self.lazy_array[i] = UNIT_MATRIX;
    }

    fn get_target_indices(&self, l: usize, r: usize) -> Vec<usize> {
        let mut ids = vec![];
        let mut l = l + self.size;
        let mut r = r + self.size;
        let lm = (l / (l & l.wrapping_neg())) >> 1;
        let rm = (r / (r & r.wrapping_neg())) >> 1;

        while 0 < l && l < r {
            if r <= rm {
                ids.push(r);
            }
            if l <= lm {
                ids.push(l);
            }
            l >>= 1;
            r >>= 1;
        }

        while l > 0 {
            ids.push(l);
            l >>= 1;
        }

        ids
    }

    fn add(&mut self, l: usize, r: usize, x: &[i64; 9]) {
        let ids = self.get_target_indices(l, r);
        for &i in ids.iter().rev() {
            self.propagate(i);
        }

        let mut l = self.size + l;
        let mut r = self.size + r;

        while l < r {
            if r & 1 != 0 {
                r -= 1;
                let mut lazy = self.lazy_array[r];
                let mut arr = self.array[r];
                self.op2(x, &mut lazy);
                self.op3(x, &mut arr);
                self.lazy_array[r] = lazy;
                self.array[r] = arr;
            }
            if l & 1 != 0 {
                let mut lazy = self.lazy_array[l];
                let mut arr = self.array[l];
                self.op2(x, &mut lazy);
                self.op3(x, &mut arr);
                self.lazy_array[l] = lazy;
                self.array[l] = arr;
                l += 1;
            }
            l >>= 1;
            r >>= 1;
        }

        for &i in ids.iter() {
            if i < self.size {
                let left = self.array[2 * i];
                let right = self.array[2 * i + 1];
                let mut current = self.array[i];
                Self::op(&mut current, &left, &right);
                self.array[i] = current;
            }
        }
    }

    fn get_max(&mut self, l: usize, r: usize) -> [i64; 3] {
        for &i in self.get_target_indices(l, r).iter().rev() {
            self.propagate(i);
        }

        let mut l = l + self.size;
        let mut r = r + self.size;
        let mut s = [0; 3];

        while l < r {
            if r & 1 != 0 {
                r -= 1;
                let val = self.array[r];
                let temp_s = s;
                Self::op(&mut s, &temp_s, &val);
            }
            if l & 1 != 0 {
                let val = self.array[l];
                let temp_s = s;
                Self::op(&mut s, &temp_s, &val);
                l += 1;
            }
            l >>= 1;
            r >>= 1;
        }
        s
    }
}

fn main() {
    let stdin = io::stdin();
    let mut lines = stdin.lock().lines();
    let first_line = lines.next().unwrap().unwrap();
    let mut it = first_line.split_whitespace();
    let n: usize = it.next().unwrap().parse().unwrap();
    let q: usize = it.next().unwrap().parse().unwrap();

    let mut queries = vec![];
    for _ in 0..q {
        let line = lines.next().unwrap().unwrap();
        let mut it = line.split_whitespace();
        let t = it.next().unwrap().parse::<usize>().unwrap();
        let l = it.next().unwrap().parse::<usize>().unwrap();
        let r = it.next().unwrap().parse::<usize>().unwrap();
        let k = it.next().unwrap().parse::<i64>().unwrap();
        queries.push((t, l, r, k));
    }

    let mut fibo = vec![0; n];
    if n > 1 {
        fibo[1] = 1;
    }
    for i in 2..n {
        fibo[i] = (fibo[i - 1] + fibo[i - 2]) % MOD;
    }

    let mut array = vec![[0, 1, 0]; n];
    for i in 0..n {
        array[i][2] = fibo[i];
    }

    let mut tree = LazySegmentTree::new(&array);

    let mut matrix1 = [0, -1, 0, 0, 1, 0, 0, 0, 1];
    let mut matrix2 = [1, -1, 0, 0, 1, 0, 0, 0, 1];
    let mut matrix3 = [-1, 0, 0, 0, 1, 0, 0, 0, 1];
    let mut matrix4 = [1, 0, -1, 0, 1, 0, 0, 0, 1];

    for (t, l, r, k) in queries {
        match t {
            0 => {
                let s = tree.get_max(l, r + 1);
                println!("{}", (s[0] * k) % MOD);
            }
            1 => {
                matrix1[1] = k;
                tree.add(l, r + 1, &matrix1);
            }
            2 => {
                matrix2[1] = k;
                tree.add(l, r + 1, &matrix2);
            }
            3 => {
                matrix3[0] = k;
                tree.add(l, r + 1, &matrix3);
            }
            4 => {
                matrix4[2] = k;
                tree.add(l, r + 1, &matrix4);
            }
            _ => {}
        }
    }
}
0