Codeforces Round #773 (Div. 1) C. Anonymity Is Important
問題
https://codeforces.com/contest/1641/problem/C
N要素の配列とQ個のクエリが来る。配列の各要素は0か1だが分からない。クエリは以下の3種類。
- L番目からR番目が全て0である。
- L番目からR番目のどれか1つ以上が1である。
- j番目の数が1ならYES、0ならNO、その時点では確定していなければN/Aを出力。
解法
予め全て読み込んでおく。これらを3回全部見る。
クエリ再生1周目
クエリのうち、まずは「L番目からR番目が全て0である」というクエリだけ処理することにする。次の2種類の操作がサポートされた遅延セグメントツリーを用意する。
- L番目からR番目までをX以上ならXに書き換える。
- L番目からR番目までのうち最大値を取り出す。
このセグメントツリーとクエリを使って、配列内の0の各要素について、その値が0と確定した時刻を記録することができる。
クエリ再生2周目
もう一度クエリを最初から全て見る。今度は「L番目からR番目のどれか1つ以上が1である」というクエリだけ処理することにする。L番目からR番目の中の0の要素数が最後までR-L個に満たなければ、このクエリによって1の要素は確定しないのでスルーして良い。L番目からR番目の要素に1の要素が1つだけあり、それがj番目と確定した場合、それ以外の0の要素が確定した時刻の最大値が分かる。その時刻かこのクエリ自体の時刻の大きいほうが、j番目が1と確定した時刻と言える。
クエリ再生3周目
今度は出力するクエリだけ処理することにする。クエリを2周したことで、各要素について、「0だと確定した時刻」「1だと確定した時刻」「何も確定していない」のいずれかが分かっている。指定された要素について、クエリ以前に確定していればYES/NOを、クエリの時点で確定していなければN/Aを出力する。
コード
use std::collections::BTreeSet; use lazy_segment_tree::LazySegmentTree; const INF: i64 = 1 << 60; fn main() { let (r, w) = (std::io::stdin(), std::io::stdout()); let mut sc = IO::new(r.lock(), w.lock()); let n: usize = sc.read(); let q: usize = sc.read(); let mut seg = LazySegmentTree::new( n, || -INF, |&left: &i64, &right: &i64| left.max(right), |&f: &Option<i64>, &x: &i64| { if let Some(f) = f { f.min(x) } else { x } }, |&f: &Option<i64>, &g: &Option<i64>| match (f, g) { (Some(x), Some(y)) => Some(x.min(y)), _ => f.or(g), }, || None, ); for i in 0..n { seg.set(i, INF); } let mut non_zero = (0..n).collect::<BTreeSet<_>>(); let mut queries = vec![]; for i in 0..q { let t: usize = sc.read(); if t == 0 { let l = sc.usize0(); let r: usize = sc.read(); let x: usize = sc.read(); queries.push((t, l, r, x)); if x == 0 { seg.apply_range(l..r, Some(i as i64)); while let Some(&x) = non_zero.range(l..r).next() { assert!(non_zero.remove(&x)); } } } else { let j = sc.usize0(); queries.push((t, j, 0, 0)); } } let mut ans_one = vec![false; n]; let mut time = vec![INF; n]; for i in 0..q { let (t, l, r, x) = queries[i]; if t == 0 && x == 1 { let min = *non_zero.range(l..).next().unwrap(); let max = *non_zero.range(..r).next_back().unwrap(); if min == max { let pos = min; let mut max = i as i64; if l < pos { max = max.max(seg.prod(l..pos)); } if (pos + 1) < r { max = max.max(seg.prod((pos + 1)..r)); } ans_one[pos] = true; time[pos] = time[pos].min(max); } } } for i in 0..n { let zero_time = seg.prod(i..(i + 1)); if zero_time != INF { time[i] = zero_time; assert!(!ans_one[i]); } } for i in 0..q { let (t, j, _, _) = queries[i]; if t == 1 { if time[j] <= i as i64 { if ans_one[j] { sc.write("YES\n"); } else { sc.write("NO\n"); } } else { sc.write("N/A\n"); } } } } pub mod lazy_segment_tree { type Range = std::ops::Range<usize>; pub struct LazySegmentTree<S, Op, E, F, Mapping, Composition, Id> { n: usize, size: usize, log: usize, data: Vec<S>, lazy: Vec<F>, op: Op, e: E, mapping: Mapping, composition: Composition, id: Id, } impl<S, Op, E, F, Mapping, Composition, Id> LazySegmentTree<S, Op, E, F, Mapping, Composition, Id> where S: Clone, E: Fn() -> S, F: Clone, Op: Fn(&S, &S) -> S, Mapping: Fn(&F, &S) -> S, Composition: Fn(&F, &F) -> F, Id: Fn() -> F, { pub fn new( n: usize, e: E, op: Op, mapping: Mapping, composition: Composition, id: Id, ) -> Self { let size = n.next_power_of_two() as usize; LazySegmentTree { n, size, log: size.trailing_zeros() as usize, data: vec![e(); 2 * size], lazy: vec![id(); size], e, op, mapping, composition, id, } } pub fn set(&mut self, mut index: usize, value: S) { assert!(index < self.n); index += self.size; for i in (1..=self.log).rev() { self.push(index >> i); } self.data[index] = value; for i in 1..=self.log { self.update(index >> i); } } pub fn get(&mut self, mut index: usize) -> S { assert!(index < self.n); index += self.size; for i in (1..=self.log).rev() { self.push(index >> i); } self.data[index].clone() } pub fn prod(&mut self, range: Range) -> S { let mut l = range.start; let mut r = range.end; assert!(l < r && r <= self.n); l += self.size; r += self.size; for i in (1..=self.log).rev() { if ((l >> i) << i) != l { self.push(l >> i); } if ((r >> i) << i) != r { self.push(r >> i); } } let mut sum_l = (self.e)(); let mut sum_r = (self.e)(); while l < r { if l & 1 != 0 { sum_l = (self.op)(&sum_l, &self.data[l]); l += 1; } if r & 1 != 0 { r -= 1; sum_r = (self.op)(&self.data[r], &sum_r); } l >>= 1; r >>= 1; } (self.op)(&sum_l, &sum_r) } pub fn all_prod(&self) -> S { self.data[1].clone() } pub fn apply(&mut self, mut index: usize, f: F) { assert!(index < self.n); index += self.size; for i in (1..=self.log).rev() { self.push(index >> i); } self.data[index] = (self.mapping)(&f, &self.data[index]); for i in 1..=self.log { self.update(index >> i); } } pub fn apply_range(&mut self, range: Range, f: F) { let mut l = range.start; let mut r = range.end; assert!(l <= r && r <= self.n); if l == r { return; } l += self.size; r += self.size; for i in (1..=self.log).rev() { if ((l >> i) << i) != l { self.push(l >> i); } if ((r >> i) << i) != r { self.push((r - 1) >> i); } } { let mut l = l; let mut r = r; while l < r { if l & 1 != 0 { self.all_apply(l, f.clone()); l += 1; } if r & 1 != 0 { r -= 1; self.all_apply(r, f.clone()); } l >>= 1; r >>= 1; } } for i in 1..=self.log { if ((l >> i) << i) != l { self.update(l >> i); } if ((r >> i) << i) != r { self.update((r - 1) >> i); } } } fn update(&mut self, k: usize) { self.data[k] = (self.op)(&self.data[2 * k], &self.data[2 * k + 1]); } fn all_apply(&mut self, k: usize, f: F) { self.data[k] = (self.mapping)(&f, &self.data[k]); if k < self.size { self.lazy[k] = (self.composition)(&f, &self.lazy[k]); } } fn push(&mut self, k: usize) { self.all_apply(2 * k, self.lazy[k].clone()); self.all_apply(2 * k + 1, self.lazy[k].clone()); self.lazy[k] = (self.id)(); } } } pub struct IO<R, W: std::io::Write>(R, std::io::BufWriter<W>); impl<R: std::io::Read, W: std::io::Write> IO<R, W> { pub fn new(r: R, w: W) -> Self { Self(r, std::io::BufWriter::new(w)) } pub fn write<S: ToString>(&mut self, s: S) { use std::io::Write; self.1.write_all(s.to_string().as_bytes()).unwrap(); } pub fn read<T: std::str::FromStr>(&mut self) -> T { use std::io::Read; let buf = self .0 .by_ref() .bytes() .map(|b| b.unwrap()) .skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r' || b == b'\t') .take_while(|&b| b != b' ' && b != b'\n' && b != b'\r' && b != b'\t') .collect::<Vec<_>>(); unsafe { std::str::from_utf8_unchecked(&buf) } .parse() .ok() .expect("Parse error.") } pub fn usize0(&mut self) -> usize { self.read::<usize>() - 1 } pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> { (0..n).map(|_| self.read()).collect() } pub fn chars(&mut self) -> Vec<char> { self.read::<String>().chars().collect() } }