結果
| 問題 | No.880 Yet Another Segment Tree Problem |
| コンテスト | |
| ユーザー |
akakimidori
|
| 提出日時 | 2020-09-21 18:20:15 |
| 言語 | Rust (1.83.0 + proconio) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 5,822 bytes |
| 記録 | |
| コンパイル時間 | 13,593 ms |
| コンパイル使用メモリ | 380,356 KB |
| 実行使用メモリ | 10,220 KB |
| 最終ジャッジ日時 | 2024-06-24 11:52:05 |
| 合計ジャッジ時間 | 18,604 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | WA * 1 |
| other | AC * 11 WA * 26 |
ソースコード
// ---------- begin Scanner(require delimiter) ----------
mod scanner {
pub struct Scanner<R> {
reader: R,
buf: Vec<u8>,
}
#[allow(dead_code)]
impl<R: std::io::BufRead> Scanner<R> {
pub fn new(reader: R) -> Self {
Scanner {
reader: reader,
buf: Vec::with_capacity(1024),
}
}
fn read(&mut self, del: u8) {
self.buf.clear();
self.reader.read_until(del, &mut self.buf).ok();
assert!(self.buf.pop().unwrap() == del);
}
pub fn next<T: std::str::FromStr>(&mut self, del: u8) -> T {
self.read(del);
std::str::from_utf8(&self.buf)
.unwrap()
.trim()
.parse::<T>()
.ok()
.unwrap()
}
pub fn next_bytes(&mut self, del: u8) -> Vec<u8> {
self.read(del);
std::str::from_utf8(&self.buf)
.unwrap()
.trim()
.bytes()
.collect()
}
}
}
// ---------- end scanner(require delimiter) ----------
use std::io::Write;
use std::cmp::*;
fn main() {
let stdin = std::io::stdin();
let mut sc = scanner::Scanner::new(stdin.lock());
run(&mut sc);
}
fn gcd(a: u64, b: u64) -> u64 {
if b == 0 {
a
} else {
gcd(b, a % b)
}
}
const INF: u64 = 1_000_000_000 + 1;
fn lcm(a: u64, b: u64) -> u64 {
if a >= INF || b >= INF {
return INF;
}
let g = gcd(a, b);
std::cmp::min(INF, a * b / g)
}
struct Node {
sum: u64,
lcm: u64,
max: u64,
len: u64,
}
impl Node {
fn new(v: u64) -> Self {
assert!(1 <= v && v <= 1_000_000_000);
Node {
sum: v,
lcm: v,
max: v,
len: 1,
}
}
fn merge(&self, rhs: &Self) -> Self {
Node {
sum: self.sum + rhs.sum,
lcm: lcm(self.lcm, rhs.lcm),
max: max(self.max, rhs.max),
len: self.len + rhs.len,
}
}
fn set(&mut self, v: u64) {
self.sum = v * self.len;
self.lcm = v;
self.max = v;
}
fn chgcd_break(&self, v: u64) -> bool {
self.lcm != INF && v % self.lcm == 0
}
fn chgcd_tag(&self) -> bool {
self.sum == self.max * self.len
}
fn chgcd(&mut self, v: u64) {
let v = gcd(self.max, v);
self.set(v);
}
fn only(&self) -> Option<u64> {
if self.sum == self.max * self.len {
Some(self.max)
} else {
None
}
}
}
fn propagate(k: usize, node: &mut [Node]) {
node[k].only().map(|v| {
for p in node[(2 * k)..].iter_mut().take(2) {
p.set(v);
}
});
}
fn update_set(k: usize, l: usize, r: usize, x: usize, y: usize, v: u64, node: &mut [Node]) {
if r <= x || y <= l {
return;
}
if x <= l && r <= y {
node[k].set(v);
return;
}
propagate(k, node);
let mid = (l + r) / 2;
update_set(2 * k, l, mid, x, y, v, node);
update_set(2 * k + 1, mid, r, x, y, v, node);
node[k] = node[2 * k].merge(&node[2 * k + 1]);
}
fn update_gcd(k: usize, l: usize, r: usize, x: usize, y: usize, v: u64, node: &mut [Node]) {
if r <= x || y <= l || node[k].chgcd_break(v) {
return;
}
if x <= l && r <= y || node[k].chgcd_tag() {
node[k].chgcd(v);
return;
}
propagate(k, node);
let mid = (l + r) / 2;
update_gcd(2 * k, l, mid, x, y, v, node);
update_gcd(2 * k + 1, mid, r, x, y, v, node);
node[k] = node[2 * k].merge(&node[2 * k + 1]);
}
fn find_max(k: usize, l: usize, r: usize, x: usize, y: usize, node: &mut [Node]) -> u64 {
if r <= x || y <= l {
return 0;
}
if x <= l && r <= y {
return node[k].max;
}
propagate(k, node);
let mid = (l + r) / 2;
let a = find_max(2 * k, l, mid, x, y, node);
let b = find_max(2 * k + 1, mid, r, x, y, node);
max(a, b)
}
fn find_sum(k: usize, l: usize, r: usize, x: usize, y: usize, node: &mut [Node]) -> u64 {
if r <= x || y <= l {
return 0;
}
if x <= l && r <= y {
return node[k].sum;
}
propagate(k, node);
let mid = (l + r) / 2;
let a = find_sum(2 * k, l, mid, x, y, node);
let b = find_sum(2 * k + 1, mid, r, x, y, node);
a + b
}
fn run<R: std::io::BufRead>(sc: &mut scanner::Scanner<R>) {
let out = std::io::stdout();
let mut out = std::io::BufWriter::new(out.lock());
let n: usize = sc.next(b' ');
let q: usize = sc.next(b'\n');
let size = n.next_power_of_two();
let mut node = (0..(2 * size)).map(|_| Node::new(1)).collect::<Vec<_>>();
for (i, p) in node[size..].iter_mut().take(n).enumerate() {
let d = if i == n - 1 {b'\n'} else {b' '};
p.set(sc.next(d));
}
for i in (1..size).rev() {
node[i] = node[2 * i].merge(&node[2 * i + 1]);
}
for _ in 0..q {
let op: u8 = sc.next(b' ');
let (l, r, x) = if op <= 2 {
let l: usize = sc.next(b' ');
let r: usize = sc.next(b' ');
let x: u64 = sc.next(b'\n');
(l - 1, r, x)
} else {
let l: usize = sc.next(b' ');
let r: usize = sc.next(b'\n');
(l - 1, r, 0)
};
if op == 1 {
update_set(1, 0, size, l, r, x, &mut node);
} else if op == 2 {
update_gcd(1, 0, size, l, r, x, &mut node);
} else if op == 3 {
let ans = find_max(1, 0, size, l, r, &mut node);
writeln!(out, "{}", ans).ok();
} else {
let ans = find_sum(1, 0, size, l, r, &mut node);
writeln!(out, "{}", ans).ok();
}
}
}
akakimidori