結果
問題 | No.880 Yet Another Segment Tree Problem |
ユーザー | akakimidori |
提出日時 | 2022-07-02 12:21:11 |
言語 | Rust (1.77.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 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1 ms
6,816 KB |
testcase_01 | AC | 1 ms
6,944 KB |
testcase_02 | AC | 2 ms
6,940 KB |
testcase_03 | AC | 1 ms
6,944 KB |
testcase_04 | AC | 1 ms
6,944 KB |
testcase_05 | AC | 1 ms
6,940 KB |
testcase_06 | AC | 2 ms
6,940 KB |
testcase_07 | AC | 2 ms
6,944 KB |
testcase_08 | AC | 2 ms
6,944 KB |
testcase_09 | AC | 2 ms
6,944 KB |
testcase_10 | AC | 2 ms
6,944 KB |
testcase_11 | AC | 190 ms
15,052 KB |
testcase_12 | AC | 176 ms
15,112 KB |
testcase_13 | AC | 135 ms
14,236 KB |
testcase_14 | AC | 188 ms
15,460 KB |
testcase_15 | AC | 206 ms
15,564 KB |
testcase_16 | AC | 208 ms
15,732 KB |
testcase_17 | AC | 164 ms
15,856 KB |
testcase_18 | AC | 159 ms
15,852 KB |
testcase_19 | AC | 92 ms
15,500 KB |
testcase_20 | AC | 96 ms
15,760 KB |
testcase_21 | AC | 94 ms
15,496 KB |
testcase_22 | AC | 94 ms
15,620 KB |
testcase_23 | AC | 95 ms
15,496 KB |
testcase_24 | AC | 89 ms
15,620 KB |
testcase_25 | AC | 89 ms
15,792 KB |
testcase_26 | AC | 90 ms
15,668 KB |
testcase_27 | AC | 88 ms
15,600 KB |
testcase_28 | AC | 91 ms
15,592 KB |
testcase_29 | AC | 168 ms
15,500 KB |
testcase_30 | AC | 175 ms
15,568 KB |
testcase_31 | AC | 194 ms
15,820 KB |
testcase_32 | AC | 38 ms
15,968 KB |
testcase_33 | AC | 80 ms
15,628 KB |
testcase_34 | AC | 87 ms
15,792 KB |
testcase_35 | AC | 89 ms
15,684 KB |
testcase_36 | AC | 84 ms
15,812 KB |
testcase_37 | AC | 81 ms
15,652 KB |
ソースコード
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) where F: 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) where F: 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) where F: 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) where F: 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 ----------