結果
| 問題 |
No.749 クエリ全部盛り
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 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
ソースコード
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);
}
_ => {}
}
}
}