結果

問題 No.880 Yet Another Segment Tree Problem
ユーザー akakimidori
提出日時 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
権限があれば一括ダウンロードができます

ソースコード

diff #
プレゼンテーションモードにする

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 ----------
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0