use std::collections::*; use std::cmp::Ordering; fn read() -> T { let mut s = String::new(); std::io::stdin().read_line(&mut s).ok(); s.trim().parse().ok().unwrap() } fn read_vec() -> Vec { read::().split_whitespace() .map(|e| e.parse().ok().unwrap()).collect() } trait BinarySearch { fn lower_bound(&self, &T) -> usize; fn upper_bound(&self, &T) -> usize; } impl BinarySearch for [T] { fn lower_bound(&self, x: &T) -> usize { let mut low = 0; let mut high = self.len(); while low != high { let mid = (low + high) / 2; match self[mid].cmp(x) { Ordering::Less => { low = mid + 1; } Ordering::Equal | Ordering::Greater => { high = mid; } } } low } fn upper_bound(&self, x: &T) -> usize { let mut low = 0; let mut high = self.len(); while low != high { let mid = (low + high) / 2; match self[mid].cmp(x) { Ordering::Less | Ordering::Equal => { low = mid + 1; } Ordering::Greater => { high = mid; } } } low } } fn main() { let n = read::(); let mut a = vec![0; n]; let mut b = vec![0; n]; for i in 0..n { let v = read_vec::(); a[i] = v[0]; b[i] = v[1]; } if n == 1 { println!("{:?}", std::cmp::min(a[0], b[0])); return; } let half = (n / 2) as u32; let mut half_cominations: Vec = Vec::new(); for i in 0..2usize.pow(half) { let mut i = i; let mut num: i64 = 0; for j in 0..half { if i % 2 == 0 { num += a[j as usize]; } else { num -= b[j as usize]; } i /= 2; } half_cominations.push(num); } half_cominations.sort(); let mut ans = std::i64::MAX; let latter_half = n as u32 - half; for i in 0..2usize.pow(latter_half) { let mut i = i; let mut num: i64 = 0; for j in half..n as u32 { if i % 2 == 0 { num += a[j as usize]; } else { num -= b[j as usize]; } i /= 2; } let lb = half_cominations.lower_bound(&-num); if lb > 0 { let upper = half_cominations[lb - 1] + num; ans = std::cmp::min(upper.abs(), ans); } if lb < half_cominations.len() { let lower = half_cominations[lb] + num; ans = std::cmp::min(lower.abs(), ans); } } println!("{:?}", ans); }