#![allow(unstable_name_collisions)] use std::collections::BTreeMap; use proconio::input; #[allow(unused)] use lib::*; #[derive(Debug)] struct BTreeMultiSet { length: usize, counts: BTreeMap, } impl BTreeMultiSet { fn new() -> Self { Self { length: 0, counts: BTreeMap::new() } } fn insert(&mut self, value: T) { self.length += 1; *self.counts.entry(value).or_default() += 1; } fn first(&self) -> Option<&T> { self.counts.keys().next() } fn last(&self) -> Option<&T> { self.counts.keys().rev().next() } fn pop_first(&mut self) -> Option { let mut count_entry = self.counts.first_entry()?; self.length -= 1; *count_entry.get_mut() -= 1; if *count_entry.get() == 0 { Some(count_entry.remove_entry().0) } else { Some(*count_entry.key()) } } fn pop_last(&mut self) -> Option { let mut count_entry = self.counts.last_entry()?; self.length -= 1; *count_entry.get_mut() -= 1; if *count_entry.get() == 0 { Some(count_entry.remove_entry().0) } else { Some(*count_entry.key()) } } } impl From<&[T]> for BTreeMultiSet { fn from(value: &[T]) -> Self { let mut ret = Self::new(); for v in value { ret.insert(*v); } ret } } fn main() { input! { n: usize, k: usize, q: usize, mut a: [i64; n], } a.sort(); let mut less = BTreeMultiSet::from(&a[..k]); let mut greater = BTreeMultiSet::from(&a[k..]); for _ in 0..q { input! { query: u8 } match query { 1 => { input! { x: i64 } less.insert(x); greater.insert(less.pop_last().unwrap()); } 2 => { input! { y: i64 } let temp = less.pop_last().unwrap(); greater.insert(temp + y); less.insert(greater.pop_first().unwrap()); } 3 => { less.last().unwrap().println(); } _ => {} } } less.dprintln(); greater.dprintln(); } #[allow(unused)] mod lib { use std::{ cmp::Ordering, fmt::{Debug, Display}, marker::PhantomData, }; use proconio::{input, source::Readable}; #[macro_export] macro_rules! min { ($l:expr $(,)?) => { $l }; ($l:expr, $($other:expr),+ $(,)?) => { std::cmp::min($l, min!($($other),*)) }; } #[macro_export] macro_rules! max { ($l:expr $(,)?) => { $l }; ($l:expr, $($other:expr),+ $(,)?) => { std::cmp::max($l, max!($($other),*)) }; } #[macro_export] macro_rules! println_exit { ($($arg:tt)*) => { { println!($($arg)*); std::process::exit(0) } }; } #[macro_export] macro_rules! all_eq { ($val:expr, $($vals:expr),*) => { $($val == $vals &&)* true }; } #[macro_export] macro_rules! multi_vec { [$val:expr; $len:expr] => { vec![$val; $len] }; [$val:expr; $len:expr, $($lens:expr),+] => { vec![multi_vec![$val; $($lens),+]; $len] }; } #[macro_export] macro_rules! array { [$($val:expr),* $(,)?] => { [$($val),*] }; [$val:expr; $len:expr] => { std::array::from_fn::<_, $len, _>(|_| $val.clone()) }; } #[macro_export] macro_rules! multi_array { [$val:expr; $len:expr] => { array![$val; $len] }; [$val:expr; $len:expr, $($lens:expr),+] => { array![multi_array![$val; $($lens),+]; $len] }; } #[macro_export] macro_rules! vec_deque { ($elem:expr; $len:expr) => { VecDeque::from(vec![$elem; $len]) }; ($($elem:expr),* $(,)?) => { VecDeque::from([$($elem),*]) } } #[macro_export] macro_rules! cmp { ($_:tt) => { true }; ($_0:tt, $_1:tt) => { true }; ($l1:tt, $l2:tt $op:tt $r:tt $($others:tt)*) => { $l1 $op $r && $l2 $op $r && cmp!($r $($others)*) }; ($l:tt $op:tt $r1:tt, $r2:tt $($others:tt)*) => { $l $op $r1 && $l $op $r2 && cmp!($r1, $r2 $($others)*) }; ($l:tt $op:tt $r:tt $($others:tt)*) => { $l $op $r && cmp!($r $($others)*) }; } #[macro_export] macro_rules! option_and_tuple { ($($opt:expr),* $(,)?) => { (|| Some(($($opt?),*)))() }; } #[macro_export] macro_rules! swap { ($l:expr, $r:expr) => { ($l, $r) = ($r, $l) }; } pub trait OrdAsign where Self: PartialOrd + Sized { fn chmax(&mut self, other: Self) -> bool { if other > *self { *self = other; true } else { false } } fn chmin(&mut self, other: Self) -> bool { if other < *self { *self = other; true } else { false } } } impl OrdAsign for T {} pub trait OptionExt { fn insert_max(&mut self, other: T) -> bool where T: PartialOrd; fn insert_min(&mut self, other: T) -> bool where T: PartialOrd; fn tuple_and(self, other: Option) -> Option<(T, U)>; } impl OptionExt for Option { fn insert_max(&mut self, other: T) -> bool where T: PartialOrd { match self { Some(s) => s.chmax(other), None => { *self = Some(other); true } } } fn insert_min(&mut self, other: T) -> bool where T: PartialOrd { match self { Some(s) => s.chmax(other), None => { *self = Some(other); true } } } fn tuple_and(self, other: Option) -> Option<(T, U)> { match (self, other) { (Some(s), Some(other)) => Some((s, other)), _ => None, } } } pub struct LenVec { t: PhantomData } impl Readable for LenVec { type Output = Vec; fn read>(source: &mut S) -> Self::Output { input! { from source, len: usize, vec: [T; len], } vec } } pub trait BoolExt { fn yesno(&self) -> &'static str; fn print_yesno(&self); fn flip(&mut self); } impl BoolExt for bool { fn yesno(&self) -> &'static str { self.then_some("Yes").unwrap_or("No") } fn print_yesno(&self) { println!("{}", self.yesno()) } fn flip(&mut self) { *self = !*self } } pub trait Sorted: Sized + AsMut<[T]> { fn sorted(mut self) -> Self { self.as_mut().sort(); self } fn sorted_by(mut self, cmp: impl FnMut(&T, &T) -> Ordering) -> Self { self.as_mut().sort_by(cmp); self } fn sorted_by_key(mut self, cmp: impl FnMut(&T) -> K) -> Self { self.as_mut().sort_by_key(cmp); self } fn rev_sorted(mut self) -> Self { self.as_mut().rev_sort(); self } } impl> Sorted for V {} pub use bit::*; pub mod bit { use std::ops::{BitAnd, Shr, ShrAssign}; pub trait Bit: Sized + BitAnd + Eq + Copy + Shr + ShrAssign { fn zero() -> Self; fn one() -> Self; fn bit

(self, pos: P) -> bool where Self: Shr { (self >> pos) & Self::one() == Self::one() } fn bits(self) -> Bits { Bits::new(self) } } #[derive(Debug, Clone)] pub struct Bits { n: T } impl Bits { fn new(n: T) -> Self { Self {n} } } impl Iterator for Bits { type Item = bool; fn next(&mut self) -> Option { if self.n == T::zero() { return None } let ret = self.n & T::one() == T::one(); self.n >>= 1; Some(ret) } } macro_rules! impl_trait { ($($type:ty)*) => { $(impl Bit for $type { #[inline(always)] fn zero() -> Self { 0 } #[inline(always)] fn one() -> Self { 1 } })*}; } impl_trait!(u8 u16 u32 u64 u128 usize); } pub trait Print: Display { fn print(&self) { print!("{self}"); } fn println(&self) { println!("{self}"); } fn eprint(&self) { eprint!("{self}"); } fn eprintln(&self) { eprintln!("{self}"); } } impl Print for T {} pub trait DebugPrint: Debug { fn dprint(&self) { eprint!("{self:?}"); } fn dprintln(&self) { eprintln!("{self:?}"); } } impl DebugPrint for T {} pub fn primes(max: usize) -> Vec { let mut is_prime = vec![true; max]; is_prime[0..=1].fill(false); for i in 2.. { if i*i >= max { break; } if is_prime[i] { let mut temp = i*2; while temp < max { is_prime[temp] = false; temp += i; } } } is_prime.into_iter().enumerate().filter(|&(_, is_prime)| is_prime).map(|(n, _)| n).collect() } pub trait CharsToString { fn to_string(&self) -> String; } impl CharsToString for [char] { fn to_string(&self) -> String { self.iter().collect() } } pub use slice_ext::*; pub mod slice_ext { use std::{fmt::Display, iter::FusedIterator}; use itertools::Itertools; pub trait SliceExt { fn rev_sort(&mut self) where T: Ord; fn get_elem>(&self, index: Idx) -> Option<&T>; fn space_separate_print(&self) where T: Display; fn line_separate_print(&self) where T: Display; fn array_windows(&self) -> ArrayWindows<'_, T, N>; } impl SliceExt for [T] { fn rev_sort(&mut self) where T: Ord { self.sort_by(|l, r| r.cmp(l)); } fn get_elem>(&self, index: Idx) -> Option<&T> { let index: usize = index.try_into().ok()?; self.get(index) } fn space_separate_print(&self) where T: Display { println!("{}", self.iter().join(" ")); } fn line_separate_print(&self) where T: Display { println!("{}", self.iter().join("\n")); } #[inline] fn array_windows(&self) -> ArrayWindows<'_, T, N> { ArrayWindows::new(self) } } struct IsNonZero; impl IsNonZero { const OK: () = assert!(N > 0, "size must be non-zero"); } #[derive(Debug, Clone)] pub struct ArrayWindows<'a, T, const N: usize> { slice: &'a [T], } impl<'a, T, const N: usize> ArrayWindows<'a, T, N> { fn new(slice: &'a [T]) -> Self { let _ = IsNonZero::::OK; Self { slice } } } impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> { type Item = &'a [T; N]; fn next(&mut self) -> Option { if self.slice.len() < N { None } else { let ret = self.slice[..N].try_into().unwrap(); self.slice = &self.slice[1..]; Some(ret) } } fn count(self) -> usize where Self: Sized { self.len() } fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } fn nth(&mut self, n: usize) -> Option { if self.len() < n + 1 { self.slice = &[]; None } else { self.slice = &self.slice[n..]; self.next() } } } impl<'a, T, const N: usize> ExactSizeIterator for ArrayWindows<'a, T, N> { fn len(&self) -> usize { self.slice.len().saturating_sub(N - 1) } } impl<'a, T, const N: usize> DoubleEndedIterator for ArrayWindows<'a, T, N> { fn next_back(&mut self) -> Option { if self.slice.len() < N { None } else { let ret = self.slice[self.slice.len() - N..].try_into().unwrap(); self.slice = &self.slice[..self.slice.len() - 1]; Some(ret) } } fn nth_back(&mut self, n: usize) -> Option { if self.len() < n + 1 { self.slice = &[]; None } else { self.slice = &self.slice[..self.slice.len() - n]; self.next_back() } } } impl<'a, T, const N: usize> FusedIterator for ArrayWindows<'a, T, N> {} } }