complete 16975.rs
This commit is contained in:
147
storage/zeta/rs/completed/16975.rs
Normal file
147
storage/zeta/rs/completed/16975.rs
Normal file
@@ -0,0 +1,147 @@
|
||||
use std::io::{BufWriter, Write, read_to_string, stdin, stdout};
|
||||
|
||||
const MOD: usize = 1_000_000_007;
|
||||
|
||||
/*
|
||||
IMPLEMENTATION MONOID-FN
|
||||
*/
|
||||
|
||||
pub trait MonoidFn<T> {
|
||||
fn call(&self, a: &T, b: &T) -> T;
|
||||
fn identity(&self) -> T;
|
||||
}
|
||||
|
||||
/*
|
||||
IMPLEMENTATION SEG-TREE ON MONOID-FN<T>
|
||||
*/
|
||||
struct SegTree<T: Clone, F>
|
||||
where
|
||||
F: MonoidFn<T>,
|
||||
{
|
||||
pub op: F,
|
||||
size: usize,
|
||||
tree: Vec<T>,
|
||||
}
|
||||
|
||||
impl<T: Clone, F> SegTree<T, F>
|
||||
where
|
||||
F: MonoidFn<T>,
|
||||
{
|
||||
fn new(arr: &Vec<T>, op: F) -> Self {
|
||||
let size = arr.len();
|
||||
|
||||
let mut tree = vec![op.identity(); size * 4];
|
||||
|
||||
let mut stack = vec![]; // (inst, index, [lo, hi))
|
||||
|
||||
stack.push((1, 0, 0, size)); // 빼면서 업데이트
|
||||
stack.push((0, 0, 0, size)); // 넣기
|
||||
|
||||
while !stack.is_empty() {
|
||||
let (inst, index, lo, hi) = stack.pop().unwrap();
|
||||
if inst == 0 {
|
||||
if hi - lo == 1 {
|
||||
tree[index] = arr[lo].clone();
|
||||
} else {
|
||||
let mid = (lo + hi) / 2;
|
||||
let left_index = index * 2 + 1;
|
||||
let right_index = index * 2 + 2;
|
||||
stack.push((1, left_index, lo, mid));
|
||||
stack.push((0, left_index, lo, mid));
|
||||
|
||||
stack.push((1, right_index, mid, hi));
|
||||
stack.push((0, right_index, mid, hi));
|
||||
}
|
||||
} else {
|
||||
if hi - lo == 1 {
|
||||
continue;
|
||||
} else {
|
||||
let left_index = index * 2 + 1;
|
||||
let right_index = index * 2 + 2;
|
||||
tree[index] = op.call(&tree[left_index], &tree[right_index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SegTree { op, size, tree }
|
||||
}
|
||||
|
||||
fn query_range(&self, idx: usize, lo: usize, hi: usize, qlo: usize, qhi: usize) -> T {
|
||||
if qlo >= hi || qhi <= lo {
|
||||
self.op.identity()
|
||||
} else if qlo <= lo && hi <= qhi {
|
||||
self.tree[idx].clone()
|
||||
} else {
|
||||
let mid = (lo + hi) / 2;
|
||||
let left_value = self.query_range(idx * 2 + 1, lo, mid, qlo, qhi);
|
||||
let right_value = self.query_range(idx * 2 + 2, mid, hi, qlo, qhi);
|
||||
self.op.call(&left_value, &right_value)
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, idx: usize, lo: usize, hi: usize, pos: usize, val: &T) {
|
||||
if pos < lo || pos >= hi {
|
||||
return;
|
||||
}
|
||||
if hi - lo == 1 {
|
||||
self.tree[idx] = val.clone();
|
||||
return;
|
||||
}
|
||||
let mid = (lo + hi) / 2;
|
||||
self.update(idx * 2 + 1, lo, mid, pos, val);
|
||||
self.update(idx * 2 + 2, mid, hi, pos, val);
|
||||
self.tree[idx] = self
|
||||
.op
|
||||
.call(&self.tree[idx * 2 + 1], &self.tree[idx * 2 + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
struct SumMono;
|
||||
|
||||
impl MonoidFn<i64> for SumMono {
|
||||
fn call(&self, a: &i64, b: &i64) -> i64 {
|
||||
a + b
|
||||
}
|
||||
fn identity(&self) -> i64 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let temp = read_to_string(stdin()).unwrap();
|
||||
let mut iter = temp
|
||||
.split_ascii_whitespace()
|
||||
.map(|x| x.parse::<i64>().unwrap());
|
||||
|
||||
let n = iter.next().unwrap() as usize;
|
||||
|
||||
let op = SumMono;
|
||||
|
||||
let arr = (0..n).map(|_| iter.next().unwrap()).collect::<Vec<_>>();
|
||||
|
||||
let diff = vec![0; n + 1];
|
||||
|
||||
let mut out = BufWriter::new(stdout());
|
||||
|
||||
let mut segtr = SegTree::new(&diff, op);
|
||||
let m = iter.next().unwrap();
|
||||
for _ in 0..m {
|
||||
let a = iter.next().unwrap();
|
||||
|
||||
if a == 2 {
|
||||
let x = iter.next().unwrap() as usize - 1;
|
||||
let res = arr[x] + segtr.query_range(0, 0, n + 1, 0, x + 1);
|
||||
writeln!(out, "{}", res).unwrap();
|
||||
} else {
|
||||
let (i, j, k) = (
|
||||
iter.next().unwrap() as usize - 1,
|
||||
iter.next().unwrap() as usize - 1,
|
||||
iter.next().unwrap(),
|
||||
);
|
||||
let qi = segtr.query_range(0, 0, n + 1, i, i + 1);
|
||||
let qj = segtr.query_range(0, 0, n + 1, j + 1, j + 2);
|
||||
segtr.update(0, 0, n + 1, i, &(qi + k));
|
||||
segtr.update(0, 0, n + 1, j + 1, &(qj - k));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user