use std::collections::BTreeMap; use std::io::{self, Read}; fn add(mp: &mut BTreeMap, price: i64, count: i64) { if count > 0 { *mp.entry(price).or_insert(0) += count; } } fn remove_some(mp: &mut BTreeMap, price: i64, count: i64, current: i64) { if count == current { mp.remove(&price); } else { *mp.get_mut(&price).unwrap() -= count; } } fn main() { let mut input = String::new(); io::stdin().read_to_string(&mut input).unwrap(); let mut it = input.split_whitespace().map(|x| x.parse::().unwrap()); let t = it.next().unwrap() as usize; let mut answers = Vec::with_capacity(t); for _ in 0..t { let n = it.next().unwrap() as usize; let k = it.next().unwrap(); let mut a = vec![0_i64; n]; let mut b = vec![0_i64; n]; let mut c = vec![0_i64; n]; let mut d = vec![0_i64; n]; for x in &mut a { *x = it.next().unwrap(); } for x in &mut b { *x = it.next().unwrap(); } for x in &mut c { *x = it.next().unwrap(); } for x in &mut d { *x = it.next().unwrap(); } let mut candidates = BTreeMap::::new(); let mut kept = 0_i64; let mut profit = 0_i128; for i in 0..n { add(&mut candidates, a[i], b[i]); kept += b[i]; let mut remain = d[i]; while remain > 0 { let Some((price, count)) = candidates.first_key_value().map(|(&p, &cnt)| (p, cnt)) else { break; }; if price >= c[i] { break; } let take = remain.min(count); profit += (c[i] - price) as i128 * take as i128; remove_some(&mut candidates, price, take, count); add(&mut candidates, c[i], take); remain -= take; } while kept > k { let (price, count) = candidates.last_key_value().map(|(&p, &cnt)| (p, cnt)).unwrap(); let take = (kept - k).min(count); remove_some(&mut candidates, price, take, count); kept -= take; } } answers.push(profit.to_string()); } println!("{}", answers.join("\n")); }