use std::io::{BufWriter, Write, read_to_string, stdin, stdout}; /* IMPLEMENTATION MONOID-FN */ pub trait MonoidFn { fn call(&self, a: &T, b: &T) -> T; fn identity(&self) -> T; } /* IMPLEMENTATION SEG-TREE ON MONOID-FN */ struct SegTree where F: MonoidFn, { pub op: F, size: usize, tree: Vec, } impl SegTree where F: MonoidFn, { fn new(arr: &Vec, 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(&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(idx * 2 + 1, lo, mid, qlo, qhi); let right_value = self.query(idx * 2 + 2, mid, hi, qlo, qhi); self.op.call(&left_value, &right_value) } } fn modify(&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.modify(idx * 2 + 1, lo, mid, pos, val); self.modify(idx * 2 + 2, mid, hi, pos, val); self.tree[idx] = self .op .call(&self.tree[idx * 2 + 1], &self.tree[idx * 2 + 2]); } } struct MonoSum; impl MonoidFn for MonoSum { 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::().unwrap()); let n = iter.next().unwrap() as usize; let op = MonoSum; let arr = (0..n).map(|_| iter.next().unwrap()).collect::>(); let mut out = BufWriter::new(stdout()); let mut segtr = SegTree::new(&arr, op); let mut m_queries = vec![]; let mut f_queries = vec![]; let m = iter.next().unwrap() as usize; let mut cnt = 0; for _ in 0..m { let i = iter.next().unwrap(); if i == 2 { f_queries.push(( iter.next().unwrap() as usize, iter.next().unwrap() as usize - 1, iter.next().unwrap() as usize, cnt, )); cnt += 1; } else { m_queries.push((iter.next().unwrap() as usize - 1, iter.next().unwrap())) } } f_queries.sort_by_key(|v| v.0); let mut curr = 0 as usize; let mut f_ptr = 0; let mf = f_queries.len(); let mut responses = vec![]; while f_ptr < mf { let (k, ql, qr, cr) = f_queries[f_ptr]; while curr < k { let (mpos, mv) = m_queries[curr]; segtr.modify(0, 0, n, mpos, &mv); curr += 1; } if k == curr { let res = segtr.query(0, 0, n, ql, qr); responses.push((cr, res)); } f_ptr += 1; } responses.sort_by_key(|x| x.0); for res in responses { writeln!(out, "{}", res.1).unwrap(); } }