結果
問題 | No.880 Yet Another Segment Tree Problem |
ユーザー |
![]() |
提出日時 | 2022-07-02 12:21:11 |
言語 | Rust (1.83.0 + proconio) |
結果 |
AC
|
実行時間 | 208 ms / 5,000 ms |
コード長 | 6,212 bytes |
コンパイル時間 | 14,322 ms |
コンパイル使用メモリ | 381,108 KB |
実行使用メモリ | 15,968 KB |
最終ジャッジ日時 | 2024-09-22 20:03:00 |
合計ジャッジ時間 | 19,415 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 1 |
other | AC * 37 |
ソースコード
fn main() {let (a, ask) = read_input();let ini = a.iter().map(|a| Node::new(*a as u64)).collect::<Vec<_>>();let mut seg = SegmentTree::new(R, ini);use std::io::*;let out = std::io::stdout();let mut out = std::io::BufWriter::new(out.lock());for query in ask {match query {Query::Assign(l, r, v) => {let v = v as u64;seg.update(l, r, |node| node.set(v));}Query::Chgcd(l, r, v) => {let v = v as u64;seg.update_bool(l, r, |node| {if v % node.lcm == 0 {return true;}node.max * node.len == node.sum && {node.set(binary_gcd(node.max, v));true}})}Query::Max(l, r) => {let mut ans = 0u64;seg.find(l, r, |node| ans = ans.max(node.max));writeln!(out, "{}", ans).ok();}Query::Sum(l, r) => {let mut ans = 0u64;seg.find(l, r, |node| ans += node.sum);writeln!(out, "{}", ans).ok();}}}}#[derive(Clone)]struct Node {len: u64,sum: u64,max: u64,lcm: u64,}impl Node {fn new(a: u64) -> Self {Node {len: 1,sum: a,max: a,lcm: a,}}fn set(&mut self, v: u64) {self.sum = v * self.len;self.max = v;self.lcm = v;}}fn lcm(a: u64, b: u64) -> u64 {const INF: u64 = 1_000_000_001;if a == INF || b == INF {INF} else {INF.min(a / binary_gcd(a, b) * b)}}struct R;impl DFSNode for R {type T = Node;fn merge(&self, p: &mut Self::T, c: &[Self::T]) {let (l, r) = (&c[0], &c[1]);p.len = l.len + r.len;p.sum = l.sum + r.sum;p.max = l.max.max(r.max);p.lcm = lcm(l.lcm, r.lcm);}fn push(&self, p: &mut Self::T, c: &mut [Self::T]) {if p.len * p.max == p.sum {let v = p.max;for c in c.iter_mut() {c.set(v);}}}}enum Query {Assign(usize, usize, u32),Chgcd(usize, usize, u32),Max(usize, usize),Sum(usize, usize),}fn read_input() -> (Vec<u32>, Vec<Query>) {let mut s = String::new();use std::io::*;std::io::stdin().read_to_string(&mut s).unwrap();let mut it = s.trim().split_whitespace().flat_map(|s| s.parse::<usize>());let mut next = || it.next().unwrap();let n = next();let q = next();let a = (0..n).map(|_| next() as u32).collect();let ask = (0..q).map(|_| {let op = next();let l = next() - 1;let r = next();match op {1 => {let x = next() as u32;Query::Assign(l, r, x)}2 => {let x = next() as u32;Query::Chgcd(l, r, x)}3 => Query::Max(l, r),_ => Query::Sum(l, r),}}).collect();(a, ask)}pub trait DFSNode {type T: Clone;fn merge(&self, p: &mut Self::T, c: &[Self::T]);fn push(&self, p: &mut Self::T, c: &mut [Self::T]);}pub struct SegmentTree<R: DFSNode> {op: R,data: Vec<R::T>,size: usize,n: usize,}impl<R: DFSNode> SegmentTree<R> {pub fn new(op: R, ini: Vec<R::T>) -> Self {assert!(ini.len() > 0);let n = ini.len();let size = n.next_power_of_two();let mut data = vec![ini[0].clone(); 2 * size];for (data, ini) in data[size..].iter_mut().zip(ini) {*data = ini;}for i in (1..size).rev() {let (f, t) = data.split_at_mut(2 * i);op.merge(&mut f[i], &t[..2]);}SegmentTree { op, data, size, n }}pub fn update<F>(&mut self, l: usize, r: usize, mut f: F)whereF: FnMut(&mut R::T),{assert!(l <= r && r <= self.n);if l == r {return;}self.dfs(1, 0, self.size, l, r, true, &mut |node| {f(node);true});}pub fn update_bool<F>(&mut self, l: usize, r: usize, mut f: F)whereF: FnMut(&mut R::T) -> bool,{assert!(l <= r && r <= self.n);if l == r {return;}self.dfs(1, 0, self.size, l, r, true, &mut f);}pub fn find<F>(&mut self, l: usize, r: usize, mut f: F)whereF: FnMut(&R::T),{assert!(l <= r && r <= self.n);if l == r {return;}self.dfs(1, 0, self.size, l, r, false, &mut |node| {f(node);true});}fn dfs<F>(&mut self, v: usize, l: usize, r: usize, x: usize, y: usize, update: bool, f: &mut F)whereF: FnMut(&mut R::T) -> bool,{if x <= l && r <= y && f(&mut self.data[v]) {return;}if r <= self.n {let (f, t) = self.data.split_at_mut(2 * v);self.op.push(&mut f[v], &mut t[..2]);}let m = (l + r) / 2;if x < m {self.dfs(2 * v, l, m, x, y, update, f);}if m < y {self.dfs(2 * v + 1, m, r, x, y, update, f);}if update && r <= self.n {let (f, t) = self.data.split_at_mut(2 * v);self.op.merge(&mut f[v], &t[..2]);}}}// ---------- begin binary_gcd ----------pub fn binary_gcd(a: u64, b: u64) -> u64 {if a == 0 || b == 0 {return a + b;}let x = a.trailing_zeros();let y = b.trailing_zeros();let mut a = a >> x;let mut b = b >> y;while a != b {let x = (a ^ b).trailing_zeros();if a < b {std::mem::swap(&mut a, &mut b);}a = (a - b) >> x;}a << x.min(y)}// ---------- end binary_gcd ----------