結果
問題 | No.1558 Derby Live |
ユーザー | fukafukatani |
提出日時 | 2021-06-25 23:05:45 |
言語 | Rust (1.77.0 + proconio) |
結果 |
AC
|
実行時間 | 876 ms / 2,000 ms |
コード長 | 16,454 bytes |
コンパイル時間 | 12,935 ms |
コンパイル使用メモリ | 384,676 KB |
実行使用メモリ | 120,224 KB |
最終ジャッジ日時 | 2024-06-25 08:49:42 |
合計ジャッジ時間 | 37,087 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 834 ms
115,988 KB |
testcase_01 | AC | 814 ms
120,224 KB |
testcase_02 | AC | 1 ms
6,940 KB |
testcase_03 | AC | 443 ms
14,660 KB |
testcase_04 | AC | 237 ms
64,800 KB |
testcase_05 | AC | 258 ms
66,524 KB |
testcase_06 | AC | 461 ms
62,096 KB |
testcase_07 | AC | 31 ms
54,492 KB |
testcase_08 | AC | 484 ms
114,340 KB |
testcase_09 | AC | 498 ms
115,796 KB |
testcase_10 | AC | 518 ms
115,812 KB |
testcase_11 | AC | 543 ms
115,820 KB |
testcase_12 | AC | 572 ms
115,888 KB |
testcase_13 | AC | 605 ms
115,872 KB |
testcase_14 | AC | 639 ms
115,888 KB |
testcase_15 | AC | 672 ms
115,828 KB |
testcase_16 | AC | 696 ms
115,876 KB |
testcase_17 | AC | 741 ms
118,744 KB |
testcase_18 | AC | 756 ms
118,912 KB |
testcase_19 | AC | 876 ms
118,836 KB |
testcase_20 | AC | 817 ms
118,712 KB |
testcase_21 | AC | 757 ms
118,824 KB |
testcase_22 | AC | 785 ms
118,744 KB |
testcase_23 | AC | 817 ms
118,724 KB |
testcase_24 | AC | 757 ms
118,764 KB |
testcase_25 | AC | 797 ms
118,820 KB |
testcase_26 | AC | 812 ms
118,768 KB |
testcase_27 | AC | 756 ms
118,736 KB |
testcase_28 | AC | 793 ms
118,556 KB |
testcase_29 | AC | 822 ms
118,728 KB |
testcase_30 | AC | 762 ms
118,712 KB |
testcase_31 | AC | 793 ms
118,680 KB |
testcase_32 | AC | 814 ms
118,884 KB |
testcase_33 | AC | 1 ms
6,944 KB |
testcase_34 | AC | 1 ms
6,940 KB |
コンパイルメッセージ
warning: type `mat` should have an upper camel case name --> src/main.rs:77:6 | 77 | type mat = [[i64; 18]; 18]; | ^^^ help: convert the identifier to upper camel case: `Mat` | = note: `#[warn(non_camel_case_types)]` on by default warning: static variable `mat_ones` should have an upper case name --> src/main.rs:18:12 | 18 | static mut mat_ones: mat = [[0i64; 18]; 18]; | ^^^^^^^^ help: convert the identifier to upper case: `MAT_ONES` | = note: `#[warn(non_upper_case_globals)]` on by default
ソースコード
#![allow(unused_imports)] use std::cmp::*; use std::collections::*; use std::io::Write; use std::ops::Bound::*; #[allow(unused_macros)] macro_rules! debug { ($($e:expr),*) => { #[cfg(debug_assertions)] $({ let (e, mut err) = (stringify!($e), std::io::stderr()); writeln!(err, "{} = {:?}", e, $e).unwrap() })* }; } static mut mat_ones: mat = [[0i64; 18]; 18]; fn main() { let v = read_vec::<usize>(); let (n, m, q) = (v[0], v[1], v[2]); let mut queries = vec![]; for _ in 0..q { queries.push(read_vec::<usize>()); } unsafe { for i in 0..n { mat_ones[i][i] = 1; } } let mut seg = Segtree::<Matmul>::new(m); for ref query in queries { match query[0] { 1 => { let d = query[1] - 1; let p = query[2..].iter().map(|&x| x - 1).collect::<Vec<_>>(); let mut mat = mat_zeros(); for i in 0..n { mat[i][p[i]] = 1; } seg.set(d, mat); } 2 => { let s = query[1] - 1; let m = seg.prod(0, s + 1); for i in 0..n { for j in 0..n { if m[j][i] == 1 { print!("{} ", j + 1); break; } } } println!(""); } _ => { let (l, r) = (query[1] - 1, query[2] - 1); let m = seg.prod(l, r + 1); let mut ans = 0; for i in 0..n { for j in 0..n { if m[j][i] == 1 { ans += (i as i64 - j as i64).abs(); break; } } } println!("{}", ans); } } } } type mat = [[i64; 18]; 18]; fn mat_zeros() -> mat { [[0i64; 18]; 18] } fn matmul(a: &mat, b: &mat) -> mat { let mut c = mat_zeros(); for i in 0..a.len() { for k in 0..b.len() { if a[i][k] == 0 { continue; } for j in 0..b[0].len() { if b[k][j] == 1 { c[i][j] += b[k][j]; break; } } } } c } pub struct Matmul; impl Monoid for Matmul { type S = mat; fn identity() -> Self::S { unsafe { mat_ones } } fn binary_operation(a: &Self::S, b: &Self::S) -> Self::S { matmul(a, b) } } fn read<T: std::str::FromStr>() -> T { let mut s = String::new(); std::io::stdin().read_line(&mut s).ok(); s.trim().parse().ok().unwrap() } fn read_vec<T: std::str::FromStr>() -> Vec<T> { read::<String>() .split_whitespace() .map(|e| e.parse().ok().unwrap()) .collect() } //https://github.com/rust-lang-ja/ac-library-rs pub mod internal_bit { // Skipped: // // - `bsf` = `__builtin_ctz`: is equivalent to `{integer}::trailing_zeros` #[allow(dead_code)] pub(crate) fn ceil_pow2(n: u32) -> u32 { 32 - n.saturating_sub(1).leading_zeros() } #[cfg(test)] mod tests { #[test] fn ceil_pow2() { // https://github.com/atcoder/ac-library/blob/2088c8e2431c3f4d29a2cfabc6529fe0a0586c48/test/unittest/bit_test.cpp assert_eq!(0, super::ceil_pow2(0)); assert_eq!(0, super::ceil_pow2(1)); assert_eq!(1, super::ceil_pow2(2)); assert_eq!(2, super::ceil_pow2(3)); assert_eq!(2, super::ceil_pow2(4)); assert_eq!(3, super::ceil_pow2(5)); assert_eq!(3, super::ceil_pow2(6)); assert_eq!(3, super::ceil_pow2(7)); assert_eq!(3, super::ceil_pow2(8)); assert_eq!(4, super::ceil_pow2(9)); assert_eq!(30, super::ceil_pow2(1 << 30)); assert_eq!(31, super::ceil_pow2((1 << 30) + 1)); assert_eq!(32, super::ceil_pow2(u32::max_value())); } } } pub mod internal_type_traits { use std::{ fmt, iter::{Product, Sum}, ops::{ Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, Mul, MulAssign, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign, }, }; // Skipped: // // - `is_signed_int_t<T>` (probably won't be used directly in `modint.rs`) // - `is_unsigned_int_t<T>` (probably won't be used directly in `modint.rs`) // - `to_unsigned_t<T>` (not used in `fenwicktree.rs`) /// Corresponds to `std::is_integral` in C++. // We will remove unnecessary bounds later. // // Maybe we should rename this to `PrimitiveInteger` or something, as it probably won't be used in the // same way as the original ACL. pub trait Integral: 'static + Send + Sync + Copy + Ord + Not<Output = Self> + Add<Output = Self> + Sub<Output = Self> + Mul<Output = Self> + Div<Output = Self> + Rem<Output = Self> + AddAssign + SubAssign + MulAssign + DivAssign + RemAssign + Sum + Product + BitOr<Output = Self> + BitAnd<Output = Self> + BitXor<Output = Self> + BitOrAssign + BitAndAssign + BitXorAssign + Shl<Output = Self> + Shr<Output = Self> + ShlAssign + ShrAssign + fmt::Display + fmt::Debug + fmt::Binary + fmt::Octal + Zero + One + BoundedBelow + BoundedAbove { } /// Class that has additive identity element pub trait Zero { /// The additive identity element fn zero() -> Self; } /// Class that has multiplicative identity element pub trait One { /// The multiplicative identity element fn one() -> Self; } pub trait BoundedBelow { fn min_value() -> Self; } pub trait BoundedAbove { fn max_value() -> Self; } macro_rules! impl_integral { ($($ty:ty),*) => { $( impl Zero for $ty { #[inline] fn zero() -> Self { 0 } } impl One for $ty { #[inline] fn one() -> Self { 1 } } impl BoundedBelow for $ty { #[inline] fn min_value() -> Self { Self::min_value() } } impl BoundedAbove for $ty { #[inline] fn max_value() -> Self { Self::max_value() } } impl Integral for $ty {} )* }; } impl_integral!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize); } pub mod segtree { use crate::internal_bit::ceil_pow2; use crate::internal_type_traits::{BoundedAbove, BoundedBelow, One, Zero}; use std::cmp::{max, min}; use std::convert::Infallible; use std::marker::PhantomData; use std::ops::{Add, Mul}; // TODO Should I split monoid-related traits to another module? pub trait Monoid { type S: Clone; fn identity() -> Self::S; fn binary_operation(a: &Self::S, b: &Self::S) -> Self::S; } pub struct Max<S>(Infallible, PhantomData<fn() -> S>); impl<S> Monoid for Max<S> where S: Copy + Ord + BoundedBelow, { type S = S; fn identity() -> Self::S { S::min_value() } fn binary_operation(a: &Self::S, b: &Self::S) -> Self::S { max(*a, *b) } } pub struct Min<S>(Infallible, PhantomData<fn() -> S>); impl<S> Monoid for Min<S> where S: Copy + Ord + BoundedAbove, { type S = S; fn identity() -> Self::S { S::max_value() } fn binary_operation(a: &Self::S, b: &Self::S) -> Self::S { min(*a, *b) } } pub struct Additive<S>(Infallible, PhantomData<fn() -> S>); impl<S> Monoid for Additive<S> where S: Copy + Add<Output = S> + Zero, { type S = S; fn identity() -> Self::S { S::zero() } fn binary_operation(a: &Self::S, b: &Self::S) -> Self::S { *a + *b } } pub struct Multiplicative<S>(Infallible, PhantomData<fn() -> S>); impl<S> Monoid for Multiplicative<S> where S: Copy + Mul<Output = S> + One, { type S = S; fn identity() -> Self::S { S::one() } fn binary_operation(a: &Self::S, b: &Self::S) -> Self::S { *a * *b } } impl<M: Monoid> Default for Segtree<M> { fn default() -> Self { Segtree::new(0) } } impl<M: Monoid> Segtree<M> { pub fn new(n: usize) -> Segtree<M> { vec![M::identity(); n].into() } } impl<M: Monoid> From<Vec<M::S>> for Segtree<M> { fn from(v: Vec<M::S>) -> Self { let n = v.len(); let log = ceil_pow2(n as u32) as usize; let size = 1 << log; let mut d = vec![M::identity(); 2 * size]; d[size..(size + n)].clone_from_slice(&v); let mut ret = Segtree { n, size, log, d }; for i in (1..size).rev() { ret.update(i); } ret } } impl<M: Monoid> Segtree<M> { pub fn set(&mut self, mut p: usize, x: M::S) { assert!(p < self.n); p += self.size; self.d[p] = x; for i in 1..=self.log { self.update(p >> i); } } pub fn get(&self, p: usize) -> M::S { assert!(p < self.n); self.d[p + self.size].clone() } pub fn prod(&self, mut l: usize, mut r: usize) -> M::S { assert!(l <= r && r <= self.n); let mut sml = M::identity(); let mut smr = M::identity(); l += self.size; r += self.size; while l < r { if l & 1 != 0 { sml = M::binary_operation(&sml, &self.d[l]); l += 1; } if r & 1 != 0 { r -= 1; smr = M::binary_operation(&self.d[r], &smr); } l >>= 1; r >>= 1; } M::binary_operation(&sml, &smr) } pub fn all_prod(&self) -> M::S { self.d[1].clone() } pub fn max_right<F>(&self, mut l: usize, f: F) -> usize where F: Fn(&M::S) -> bool, { assert!(l <= self.n); assert!(f(&M::identity())); if l == self.n { return self.n; } l += self.size; let mut sm = M::identity(); while { // do while l % 2 == 0 { l >>= 1; } if !f(&M::binary_operation(&sm, &self.d[l])) { while l < self.size { l *= 2; let res = M::binary_operation(&sm, &self.d[l]); if f(&res) { sm = res; l += 1; } } return l - self.size; } sm = M::binary_operation(&sm, &self.d[l]); l += 1; // while { let l = l as isize; (l & -l) != l } } {} self.n } pub fn min_left<F>(&self, mut r: usize, f: F) -> usize where F: Fn(&M::S) -> bool, { assert!(r <= self.n); assert!(f(&M::identity())); if r == 0 { return 0; } r += self.size; let mut sm = M::identity(); while { // do r -= 1; while r > 1 && r % 2 == 1 { r >>= 1; } if !f(&M::binary_operation(&self.d[r], &sm)) { while r < self.size { r = 2 * r + 1; let res = M::binary_operation(&self.d[r], &sm); if f(&res) { sm = res; r -= 1; } } return r + 1 - self.size; } sm = M::binary_operation(&self.d[r], &sm); // while { let r = r as isize; (r & -r) != r } } {} 0 } fn update(&mut self, k: usize) { self.d[k] = M::binary_operation(&self.d[2 * k], &self.d[2 * k + 1]); } } // Maybe we can use this someday // ``` // for i in 0..=self.log { // for j in 0..1 << i { // print!("{}\t", self.d[(1 << i) + j]); // } // println!(); // } // ``` pub struct Segtree<M> where M: Monoid, { // variable name is _n in original library n: usize, size: usize, log: usize, d: Vec<M::S>, } #[cfg(test)] mod tests { use crate::segtree::Max; use crate::Segtree; #[test] fn test_max_segtree() { let base = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3]; let n = base.len(); let segtree: Segtree<Max<_>> = base.clone().into(); check_segtree(&base, &segtree); let mut segtree = Segtree::<Max<_>>::new(n); let mut internal = vec![i32::min_value(); n]; for i in 0..n { segtree.set(i, base[i]); internal[i] = base[i]; check_segtree(&internal, &segtree); } segtree.set(6, 5); internal[6] = 5; check_segtree(&internal, &segtree); segtree.set(6, 0); internal[6] = 0; check_segtree(&internal, &segtree); } //noinspection DuplicatedCode fn check_segtree(base: &[i32], segtree: &Segtree<Max<i32>>) { let n = base.len(); #[allow(clippy::needless_range_loop)] for i in 0..n { assert_eq!(segtree.get(i), base[i]); } for i in 0..=n { for j in i..=n { assert_eq!( segtree.prod(i, j), base[i..j].iter().max().copied().unwrap_or(i32::min_value()) ); } } assert_eq!( segtree.all_prod(), base.iter().max().copied().unwrap_or(i32::min_value()) ); for k in 0..=10 { let f = |&x: &i32| x < k; for i in 0..=n { assert_eq!( Some(segtree.max_right(i, f)), (i..=n) .filter(|&j| f(&base[i..j] .iter() .max() .copied() .unwrap_or(i32::min_value()))) .max() ); } for j in 0..=n { assert_eq!( Some(segtree.min_left(j, f)), (0..=j) .filter(|&i| f(&base[i..j] .iter() .max() .copied() .unwrap_or(i32::min_value()))) .min() ); } } } } } use segtree::*;