結果
| 問題 |
No.1673 Lamps on a line
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2021-09-10 21:47:40 |
| 言語 | Rust (1.83.0 + proconio) |
| 結果 |
AC
|
| 実行時間 | 273 ms / 2,000 ms |
| コード長 | 8,276 bytes |
| コンパイル時間 | 15,634 ms |
| コンパイル使用メモリ | 401,240 KB |
| 実行使用メモリ | 27,232 KB |
| 最終ジャッジ日時 | 2024-06-11 23:19:56 |
| 合計ジャッジ時間 | 18,351 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 11 |
ソースコード
#![allow(unused_imports, unused_macros, dead_code)]
use std::{cmp::*, collections::*};
fn main() {
let mut sc = Scanner::new();
let n: usize = sc.cin();
let q: usize = sc.cin();
let v = vec![Sum(0, 1); n];
let mut v = LampLine::from(v);
for _ in 0..q {
let l = sc.usize1();
let r = sc.usize1();
v.update(l..r + 1, Toggle::Do);
let res = v.product(0..n + 1);
put!(res.0);
}
}
// @sequence/tree/ranged_rmq
// @algebra/act_assign
// @algebra/act
/// Algebra - Act
pub trait Act<X> {
fn act(&self, x: X) -> X;
}
// @algebra/monoid
/// Algebra - Def of Monoid (*, 1)
pub trait Monoid: std::ops::Mul<Output = Self>
where
Self: std::marker::Sized,
{
fn unit() -> Self;
}
#[macro_export]
macro_rules! monoid {
(
[ $( $params:tt )* ]
for $type:ty;
unit = $unit:expr;
mul($self:ident, $y:ident) = $code:block
$(;)*
) => {
impl<$($params)*> std::ops::Mul for $type {
type Output = Self;
fn mul($self, $y: Self) -> Self { $code }
}
impl<$($params)*> Monoid for $type {
fn unit() -> Self { $unit }
}
};
(
for $type:ty;
unit = $unit:expr;
mul($self:ident, $y:ident) = $code:block
$(;)*
) => {
monoid! { [] for $type; unit = $unit; mul($self, $y) = $code; }
};
}
// @algebra/monoid_sumprod
/// Algebra - Def of Monoid (i64, +)
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Sum(i64, i64);
monoid! {
for Sum;
unit = Sum(0, 1);
mul(self, other) = {
Self(self.0 + other.0, self.1 + other.1)
};
}
/// Act for Sum
#[derive(Debug, Clone, Copy)]
enum Toggle {
Do,
Nothing,
}
use Toggle::*;
impl std::ops::Mul for Toggle {
type Output = Self;
fn mul(self, other: Self) -> Self {
match (self, &other) {
(Do, Do) => Nothing,
(Nothing, Nothing) => Nothing,
_ => Do,
}
}
}
impl Act<Sum> for Toggle {
fn act(&self, x: Sum) -> Sum {
match (*self, x) {
(Do, Sum(x, length)) => Sum(length - x, length),
_ => x,
}
}
}
impl Monoid for Toggle {
fn unit() -> Self {
Nothing
}
}
// @sequence/tree/lazy_segment_tree
/// Sequence - Lazy Segment Tree
#[derive(Debug, Clone)]
pub struct LazySegmentTree<X, M> {
length: usize, // of leaves
length_upper: usize, // power of 2
size: usize, // of nodes
data: Vec<X>,
act: Vec<M>,
}
impl<X: Copy + Monoid, M: Copy + Monoid + Act<X>> LazySegmentTree<X, M> {
pub fn new(length: usize) -> Self {
let mut length_upper = 1;
while length_upper < length {
length_upper *= 2;
}
let size = length_upper * 2 - 1;
let data = vec![X::unit(); size];
let act = vec![M::unit(); size];
LazySegmentTree {
length,
length_upper,
size,
data,
act,
}
}
pub fn from(xs: Vec<X>) -> Self {
let mut tree = Self::new(xs.len());
for i in 0..xs.len() {
tree.data[tree.size / 2 + i] = xs[i];
}
for i in (0..tree.size / 2).rev() {
tree.data[i] = tree.data[2 * i + 1] * tree.data[2 * i + 2];
}
tree
}
fn propagation(&mut self, idx: usize) {
if idx < self.size / 2 {
self.act[idx * 2 + 1] = self.act[idx * 2 + 1] * self.act[idx];
self.act[idx * 2 + 2] = self.act[idx * 2 + 2] * self.act[idx];
}
self.data[idx] = self.act[idx].act(self.data[idx]);
self.act[idx] = M::unit();
}
fn update_sub(
&mut self,
range: std::ops::Range<usize>,
m: M,
idx: usize,
focus: std::ops::Range<usize>,
) {
self.propagation(idx);
if focus.end <= range.start || range.end <= focus.start {
return;
}
if range.start <= focus.start && focus.end <= range.end {
self.act[idx] = self.act[idx] * m;
self.propagation(idx);
} else if idx < self.data.len() / 2 {
let mid = (focus.start + focus.end) / 2;
self.update_sub(range.clone(), m, idx * 2 + 1, focus.start..mid);
self.update_sub(range.clone(), m, idx * 2 + 2, mid..focus.end);
self.data[idx] = self.data[idx * 2 + 1] * self.data[idx * 2 + 2];
}
}
pub fn update(&mut self, range: std::ops::Range<usize>, m: M) {
self.update_sub(range, m, 0, 0..self.length_upper);
}
fn product_sub(
&mut self,
range: std::ops::Range<usize>,
idx: usize,
focus: std::ops::Range<usize>,
) -> X {
self.propagation(idx);
if focus.end <= range.start || range.end <= focus.start {
X::unit()
} else if range.start <= focus.start && focus.end <= range.end {
self.data[idx]
} else {
let mid = (focus.start + focus.end) / 2;
let a = self.product_sub(range.clone(), idx * 2 + 1, focus.start..mid);
let b = self.product_sub(range.clone(), idx * 2 + 2, mid..focus.end);
a * b
}
}
pub fn product(&mut self, range: std::ops::Range<usize>) -> X {
self.product_sub(range, 0, 0..self.length_upper)
}
pub fn index(&mut self, i: usize) -> X {
self.product(i..i + 1)
}
pub fn to_vec(&mut self) -> Vec<X> {
(0..self.length).map(|i| self.index(i)).collect()
}
}
impl<X: std::fmt::Debug, M: std::fmt::Debug> LazySegmentTree<X, M> {
pub fn debug(&self) {
#[cfg(debug_assertions)]
for i in 0..self.size {
if i > 0 && (i + 1).count_ones() == 1 {
eprintln!();
}
eprint!("{:?} / {:?}; ", &self.data[i], &self.act[i]);
}
eprintln!();
}
}
type LampLine = LazySegmentTree<Sum, Toggle>;
// {{{
use std::io::{self, Write};
use std::str::FromStr;
struct Scanner {
stdin: io::Stdin,
buffer: VecDeque<String>,
}
impl Scanner {
fn new() -> Self {
Self {
stdin: io::stdin(),
buffer: VecDeque::new(),
}
}
fn cin<T: FromStr>(&mut self) -> T {
while self.buffer.is_empty() {
let mut line = String::new();
let _ = self.stdin.read_line(&mut line);
for w in line.split_whitespace() {
self.buffer.push_back(String::from(w));
}
}
self.buffer.pop_front().unwrap().parse::<T>().ok().unwrap()
}
fn usize1(&mut self) -> usize {
self.cin::<usize>() - 1
}
fn chars(&mut self) -> Vec<char> {
self.cin::<String>().chars().collect()
}
fn vec<T: FromStr>(&mut self, n: usize) -> Vec<T> {
(0..n).map(|_| self.cin()).collect()
}
}
fn flush() {
std::io::stdout().flush().unwrap();
}
#[macro_export]
macro_rules! min {
(.. $x:expr) => {{
let mut it = $x.iter();
it.next().map(|z| it.fold(z, |x, y| min!(x, y)))
}};
($x:expr) => ($x);
($x:expr, $($ys:expr),*) => {{
let t = min!($($ys),*);
if $x < t { $x } else { t }
}}
}
#[macro_export]
macro_rules! max {
(.. $x:expr) => {{
let mut it = $x.iter();
it.next().map(|z| it.fold(z, |x, y| max!(x, y)))
}};
($x:expr) => ($x);
($x:expr, $($ys:expr),*) => {{
let t = max!($($ys),*);
if $x > t { $x } else { t }
}}
}
#[macro_export]
macro_rules! trace {
($x:expr) => {
#[cfg(debug_assertions)]
eprintln!(">>> {} = {:?}", stringify!($x), $x)
};
($($xs:expr),*) => { trace!(($($xs),*)) }
}
#[macro_export]
macro_rules! put {
(.. $x:expr) => {{
let mut it = $x.iter();
if let Some(x) = it.next() { print!("{}", x); }
for x in it { print!(" {}", x); }
println!("");
}};
($x:expr) => { println!("{}", $x) };
($x:expr, $($xs:expr),*) => { print!("{} ", $x); put!($($xs),*) }
}
#[macro_export]
macro_rules! ndarray {
($x:expr;) => {
$x
};
($x:expr; $size:expr $( , $rest:expr )*) => {
vec![ndarray!($x; $($rest),*); $size]
};
}
// }}}