tipstar0125 / atcoder

atcoder
6 stars 0 forks source link

Kth Sum #14

Open tipstar0125 opened 7 months ago

tipstar0125 commented 7 months ago
tipstar0125 commented 7 months ago
#[derive(Debug, Clone)]
struct KthSum {
    N: usize,
    K: usize,
    S: isize,
    large: BTreeSet<(isize, usize)>,
    small: BTreeSet<(isize, usize)>,
}

impl KthSum {
    fn new(N: usize, K: usize) -> Self {
        let mut large = BTreeSet::new();
        let mut small = BTreeSet::new();
        for i in 0..K {
            small.insert((0, i));
        }
        for i in K..N {
            large.insert((0, i));
        }
        KthSum {
            N,
            K,
            S: 0,
            large,
            small,
        }
    }
    fn balance(&mut self) {
        while self.small.len() > self.K {
            let p = *self.small.iter().next_back().unwrap();
            self.small.remove(&p);
            self.large.insert(p);
            self.S -= p.0;
        }
        if self.small.is_empty() || self.large.is_empty() {
            return;
        }
        while self.large.iter().next().unwrap().0 < self.small.iter().next_back().unwrap().0 {
            let large_min = *self.large.iter().next().unwrap();
            let small_max = *self.small.iter().next_back().unwrap();
            self.large.remove(&large_min);
            self.small.remove(&small_max);
            self.large.insert(small_max);
            self.small.insert(large_min);
            self.S += large_min.0 - small_max.0;
        }
    }
    fn add(&mut self, p: (isize, usize)) {
        self.small.insert(p);
        self.S += p.0;
        self.balance();
    }
    fn remove(&mut self, p: (isize, usize)) {
        if self.small.remove(&p) {
            self.S -= p.0;
        } else {
            self.large.remove(&p);
        }
        self.balance();
    }
}
tipstar0125 commented 7 months ago
#[derive(Debug, Clone)]
struct KthSum {
    N: usize,
    K: usize,
    S: isize,
    large: BTreeSet<(isize, usize)>,
    small: BTreeSet<(isize, usize)>,
}

impl KthSum {
    fn new(N: usize, K: usize) -> Self {
        let mut large = BTreeSet::new();
        let mut small = BTreeSet::new();
        for i in 0..K {
            large.insert((0, i));
        }
        for i in K..N {
            small.insert((0, i));
        }
        KthSum {
            N,
            K,
            S: 0,
            large,
            small,
        }
    }
    fn balance(&mut self) {
        while self.large.len() > self.K {
            let p = *self.large.iter().next().unwrap();
            self.large.remove(&p);
            self.small.insert(p);
            self.S -= p.0;
        }
        if self.small.is_empty() || self.large.is_empty() {
            return;
        }
        while self.large.iter().next().unwrap().0 < self.small.iter().next_back().unwrap().0 {
            let large_min = *self.large.iter().next().unwrap();
            let small_max = *self.small.iter().next_back().unwrap();
            self.large.remove(&large_min);
            self.small.remove(&small_max);
            self.large.insert(small_max);
            self.small.insert(large_min);
            self.S += small_max.0 - large_min.0;
        }
    }
    fn add(&mut self, p: (isize, usize)) {
        self.large.insert(p);
        self.S += p.0;
        self.balance();
    }
    fn remove(&mut self, p: (isize, usize)) {
        if self.large.remove(&p) {
            self.S -= p.0;
        } else {
            self.small.remove(&p);
        }
        self.balance();
    }
}
tipstar0125 commented 7 months ago
tipstar0125 commented 7 months ago

Rustはmultisetがないので、タプルで重複しないユニークな値(例えば、配列のindex)を使うことで同様の処理を行う。 参考:https://namacha411.hatenablog.com/entry/2022/02/28/194540