use proconio::{fastout, input}; mod mylib { pub struct SegmentTree { container: Vec>, } pub trait Monoid { type T: Clone; const DEFAULT: Self::T; fn op(a: &Self::T, b: &Self::T) -> Self::T; } impl SegmentTree { pub fn update(&mut self, index: usize, value: S::T) { self.container[0][index] = value; for layer in 1..self.container.len() { self.container[layer][index >> layer] = S::op( &self.container[layer - 1][(index >> layer) << 1], &self.container[layer - 1][((index >> layer) << 1) | 1], ); } } pub fn range_pick_up(&self, mut l: usize, mut r: usize) -> S::T { let mut ans_l = S::DEFAULT; let mut ans_r = S::DEFAULT; for layer in 0..self.container.len() { if l >= r { break; } if (l & 1) == 1 { ans_l = S::op(&ans_l, &self.container[layer][l]); l += 1; } if (r & 1) == 1 { ans_r = S::op(&self.container[layer][r - 1], &ans_r); // r -= 1; } l >>= 1; r >>= 1; } S::op(&ans_l, &ans_r) } } impl From> for SegmentTree { fn from(mut value: Vec) -> Self { let mut st = Self { container: Vec::>::with_capacity(30), }; if value.is_empty() { return st; } value.extend(vec![ S::DEFAULT; value.len().next_power_of_two() - value.len() ]); st.container.push(value); let mut layer: usize = 1; while (st.container.last().unwrap().len() >> 1) > 0 { st.container .push(vec![S::DEFAULT; st.container.last().unwrap().len() >> 1]); for i in 0..st.container.last().unwrap().len() { st.container[layer][i] = S::op( &st.container[layer - 1][i << 1], &st.container[layer - 1][(i << 1) | 1], ); } layer += 1; } st } } impl Into> for SegmentTree { fn into(mut self) -> Vec { self.container.swap_remove(0) } } impl std::ops::Index for SegmentTree { type Output = S::T; fn index(&self, index: usize) -> &Self::Output { &self.container[0][index] } } } struct S64 {} impl mylib::Monoid for S64 { type T = i64; const DEFAULT: Self::T = 0; fn op(a: &Self::T, b: &Self::T) -> Self::T { *a + *b } } struct S32 {} impl mylib::Monoid for S32 { type T = i32; const DEFAULT: Self::T = 0; fn op(a: &Self::T, b: &Self::T) -> Self::T { *a + *b } } #[fastout] fn main() { input! { n: usize, m: usize, residents: [(i32, u32, u32); n], queries: [(u32, u32, u32, u32)], } println!("{}", output(solve(prepare(m, residents), queries))); } fn prepare( m: usize, residents: Vec<(i32, u32, u32)>, ) -> (Vec, Vec, Vec<(u32, u32, u32)>, i64) { let n = residents.len(); let mut cur_sum = 0; let mut residents_info = Vec::with_capacity(n + 1); let mut weight_imos = vec![0; m + 2]; let mut rate = Vec::with_capacity(m + 1); rate.push(0); residents_info.push((0, 0, 0)); rate.extend(residents.into_iter().enumerate().map(|(i, (a, l, r))| { weight_imos[l as usize] += 1; weight_imos[(r + 1) as usize] -= 1; cur_sum += a as i64 * ((r + 1) - l) as i64; residents_info.push(((i + 1) as u32, l, r)); a as i64 })); rate.extend(vec![0; m - n]); let mut weight = weight_imos.clone(); for i in 1..=n { weight[i] += weight[i - 1]; cur_sum -= rate[i] as i64 * weight[i] as i64; } (weight_imos, rate, residents_info, cur_sum) } fn solve( (weight_imos, rate, mut residents_info, mut cur_sum): ( Vec, Vec, Vec<(u32, u32, u32)>, i64, ), queries: Vec<(u32, u32, u32, u32)>, ) -> Vec { let mut ans = Vec::with_capacity(queries.len()); let mut weight_imos_st = mylib::SegmentTree::::from(weight_imos); let mut rate_st = mylib::SegmentTree::::from(rate); for (x, y, u, v) in queries { let (pos, l, r) = &mut residents_info[x as usize]; let rate = rate_st[*pos as usize]; cur_sum -= rate * ((*r + 1) - *l) as i64; cur_sum += rate_st.range_pick_up(*l as usize, (*r + 1) as usize); rate_st.update(*pos as usize, 0); weight_imos_st.update(*l as usize, weight_imos_st[*l as usize] - 1); weight_imos_st.update((*r + 1) as usize, weight_imos_st[(*r + 1) as usize] + 1); cur_sum += rate * weight_imos_st.range_pick_up(0, (*pos + 1) as usize) as i64; (*pos, *l, *r) = (y, u, v); cur_sum -= rate * weight_imos_st.range_pick_up(0, (*pos + 1) as usize) as i64; rate_st.update(*pos as usize, rate); weight_imos_st.update(*l as usize, weight_imos_st[*l as usize] + 1); weight_imos_st.update((*r + 1) as usize, weight_imos_st[(*r + 1) as usize] - 1); cur_sum -= rate_st.range_pick_up(*l as usize, (*r + 1) as usize); cur_sum += rate * ((*r + 1) - *l) as i64; ans.push(cur_sum); } ans } fn output(ans: Vec) -> String { ans.into_iter() .map(|x| x.to_string()) .collect::>() .join("\n") }