Problem:
Score : 700 points

Problem Statement

We will define the median of a sequence b of length M, as follows:

Let b' be the sequence obtained by sorting b in non-decreasing order. Then, the value of the (M / 2 + 1)-th element of b' is the median of b. Here, / is integer division, rounding down.

For example, the median of (10, 30, 20) is 20; the median of (10, 30, 20, 40) is 30; the median of (10, 10, 10, 20, 30) is 10.

Snuke comes up with the following problem.

You are given a sequence a of length N.
For each pair (l, r) (1 \leq l \leq r \leq N), let m_{l, r} be the median of the contiguous subsequence (a_l, a_{l + 1}, ..., a_r) of a.
We will list m_{l, r} for all pairs (l, r) to create a new sequence m.
Find the median of m.

Constraints

1 \leq N \leq 10^5

a_i is an integer.

1 \leq a_i \leq 10^9

Input

Input is given from Standard Input in the following format:

N
a_1 a_2 ... a_N

Output

Print the median of m.

Sample Input 1

3
10 30 20

Sample Output 1

30

The median of each contiguous subsequence of a is as follows:

The median of (10) is 10.

The median of (30) is 30.

The median of (20) is 20.

The median of (10, 30) is 30.

The median of (30, 20) is 30.

The median of (10, 30, 20) is 20.

Thus, m = (10, 30, 20, 30, 30, 20) and the median of m is 30.

Sample Input 2

1
10

Sample Output 2

10

Sample Input 3

10
5 9 5 9 8 9 3 5 4 3

Sample Output 3

8

Solution in Rust (1.15.1) (judge verdict: Accepted)

pub trait FromFragments: Sized {
    fn fragments_count() -> usize;
    fn from_fragments(fragments: &[&str]) -> Result<Self, String>;
}
impl FromFragments for () {
    fn fragments_count() -> usize {
        1
    }
    fn from_fragments(_fragments: &[&str]) -> Result<(), String> {
        Ok(())
    }
}
impl FromFragments for String {
    fn fragments_count() -> usize {
        1
    }
    fn from_fragments(fragments: &[&str]) -> Result<String, String> {
        Ok(fragments[0].to_string())
    }
}
macro_rules ! impl_from_fragments { ( $ ( $ t : ty ) * ) => { $ ( impl FromFragments for $ t { fn fragments_count ( ) -> usize { 1 } fn from_fragments ( fragments : & [ & str ] ) -> Result <$ t , String > { use std :: str :: FromStr ; <$ t >:: from_str ( fragments [ 0 ] ) . map_err ( | _ | { format ! ( "cannot parse \"{}\" as {}" , fragments [ 0 ] , stringify ! ( $ t ) ) } ) } } ) * } ; }
impl_from_fragments ! ( isize usize i8 u8 i16 u16 i32 u32 i64 u64 f32 f64 ) ;
pub trait FromLine: Sized {
    fn from_line(line: &str) -> Result<Self, String>;
}
fn split_into_fragments(line: &str) -> Vec<&str> {
    line.trim_right_matches('\n').split_whitespace().collect()
}
impl<T: FromFragments> FromLine for T {
    fn from_line(line: &str) -> Result<T, String> {
        let fragments = split_into_fragments(line);
        if fragments.len() != T::fragments_count() {
            return Err(format!(
                "line \"{}\" has {} fragments, expected {}",
                line,
                fragments.len(),
                T::fragments_count()
            ));
        }
        T::from_fragments(&fragments)
    }
}
impl<T: FromFragments> FromLine for Vec<T> {
    fn from_line(line: &str) -> Result<Vec<T>, String> {
        let n = T::fragments_count();
        let fragments = split_into_fragments(line);
        if fragments.len() % n != 0 {
            return Err(format!(
                "line \"{}\" has {} fragments, expected multiple of {}",
                line,
                fragments.len(),
                n
            ));
        }
        let mut result = Vec::new();
        for chunk in fragments.chunks(n) {
            match T::from_fragments(chunk) {
                Ok(v) => result.push(v),
                Err(msg) => {
                    let flagment_msg = if n == 1 {
                        format!("fragment {}", result.len())
                    } else {
                        let l = result.len();
                        format!("fragments {}-{}", n * l + 1, (n + 1) * l)
                    };
                    return Err(format!("{} of line \"{}\": {}", flagment_msg, line, msg));
                }
            }
        }
        Ok(result)
    }
}
macro_rules ! impl_from_fragments_for_tuples { ( $ t : ident $ var : ident $ count : expr ) => ( ) ; ( $ t : ident $ var : ident $ count : expr ; $ ( $ inner_t : ident $ inner_var : ident $ inner_count : expr ) ;* ) => { impl_from_fragments_for_tuples ! ( $ ( $ inner_t $ inner_var $ inner_count ) ;* ) ; impl <$ t : FromFragments , $ ( $ inner_t : FromFragments ) ,*> FromFragments for ( $ t , $ ( $ inner_t ) ,* ) { fn fragments_count ( ) -> usize { let mut n = <$ t >:: fragments_count ( ) ; $ ( n += <$ inner_t >:: fragments_count ( ) ; ) * n } # [ allow ( unused_assignments ) ] fn from_fragments ( fragments : & [ & str ] ) -> Result < ( $ t , $ ( $ inner_t ) ,* ) , String > { let mut start = 0 ; let $ var = <$ t >:: from_fragments ( & fragments [ start .. start +<$ t >:: fragments_count ( ) ] ) ?; start += <$ t >:: fragments_count ( ) ; $ ( let $ inner_var = <$ inner_t >:: from_fragments ( & fragments [ start .. start +<$ inner_t >:: fragments_count ( ) ] ) ?; start += <$ inner_t >:: fragments_count ( ) ; ) * Ok ( ( $ var , $ ( $ inner_var ) ,* ) ) } } } }
impl_from_fragments_for_tuples ! ( T4 x4 4 ; T3 x3 3 ; T2 x2 2 ; T1 x1 1 ) ;
#[macro_export]
macro_rules ! read { ( ) => { let mut line = String :: new ( ) ; std :: io :: stdin ( ) . read_line ( & mut line ) . unwrap ( ) ; } ; ( $ pat : pat = $ t : ty ) => { let mut line = String :: new ( ) ; std :: io :: stdin ( ) . read_line ( & mut line ) . unwrap ( ) ; let $ pat = <$ t >:: from_line ( & line ) . unwrap ( ) ; } ; ( $ ( $ pat : pat = $ t : ty ) ,+ ) => { read ! ( ( $ ( $ pat ) ,* ) = ( $ ( $ t ) ,* ) ) ; } ; }
#[macro_export]
macro_rules ! readls { ( $ ( $ pat : pat = $ t : ty ) ,+ ) => { $ ( read ! ( $ pat = $ t ) ; ) * } }
pub fn read_vec<T: FromLine>() -> Vec<T> {
    use std::io::{self, BufRead};
    let stdin = io::stdin();
    let result = stdin
        .lock()
        .lines()
        .map(|line_result| {
            let line = line_result.expect("read from stdin failed");
            T::from_line(&line).unwrap()
        }).collect();
    result
}
#[macro_export]
macro_rules ! read_loop { ( $ pat : pat = $ t : ty ; $ block : block ) => { use std :: io :: BufRead ; let stdin = std :: io :: stdin ( ) ; for line in stdin . lock ( ) . lines ( ) { let line = line . expect ( "read from stdin failed" ) ; let $ pat = <$ t >:: from_line ( & line ) . unwrap ( ) ; $ block } } ; ( $ ( $ pat : pat = $ t : ty ) ,* ; $ block : block ) => { read_loop ! ( ( $ ( $ pat ) ,* ) = ( $ ( $ t ) ,* ) ; $ block ) ; } }
#[macro_export]
macro_rules ! readn_loop { ( $ n : expr ; $ pat : pat = $ t : ty ; $ block : block ) => { use std :: io :: BufRead ; let stdin = std :: io :: stdin ( ) ; { let lock = stdin . lock ( ) ; for _ in 0 ..$ n { let line = String :: new ( ) ; lock . read_line ( & mut line ) . expect ( "read from stdin failed" ) ; let $ pat = <$ t >:: from_line ( & line ) . unwrap ( ) ; $ block } } } ; ( $ n : expr ; $ ( $ pat : pat = $ t : ty ) ,* ; $ block : block ) => { read_times_loop ! ( $ n ; ( $ ( $ pat ) ,* ) = ( $ ( $ t ) ,* ) ; $ block ) ; } }

use std::cmp::Ord;

fn count_invs<T: Ord + Copy>(seq: &[T]) -> u64 {
    fn merge<T: Ord + Copy>(left: &[T], right: &[T]) -> (Vec<T>, u64) {
        let mut result = Vec::new();
        let mut count = 0;
        let mut index_l = 0;
        let mut index_r = 0;

        while index_l < left.len() && index_r < right.len() {
            let l = left[index_l];
            let r = right[index_r];
            if l <= r {
                result.push(l);
                index_l += 1;
            } else {
                result.push(r);
                index_r += 1;
                count += (left.len() - index_l) as u64;
            }
        }

        if index_l < left.len() {
            result.extend_from_slice(&left[index_l..]);
        } else if index_r < right.len() {
            result.extend_from_slice(&right[index_r..]);
        }

        (result, count)
    }

    fn sub<T: Ord + Copy>(seq: &[T]) -> (Vec<T>, u64) {
        if seq.len() <= 1 {
            (seq.to_vec(), 0)
        } else {
            let mid = seq.len() / 2;
            let (left, n_l) = sub(&seq[..mid]);
            let (right, n_r) = sub(&seq[mid..]);
            let (merged, n) = merge(&left, &right);
            (merged, n_l + n_r + n)
        }
    }

    sub(seq).1
}

use std::ops::Add;
use std::default::Default;

fn cumulate_with_sentinel<T: Add<Output = T> + Default + Copy>(seq: &[T]) -> Vec<T> {
    let mut result = vec![T::default()];
    for x in seq {
        let next = *result.last().unwrap() + *x;
        result.push(next);
    }
    result
}

fn is_ans_ge(x: u32, aa: &[u32]) -> bool {
    let signs: Vec<i64> = aa.iter().map(|&a| if x <= a { 1 } else { -1 }).collect();
    let ss = cumulate_with_sentinel(&signs);
    let n = aa.len() as u64;
    // println!("{}: {}", x, count_invs_and_eqs(&ss));
    count_invs(&ss) <= n * (n+1) / 4
}

fn main() {
    readls!(_ = (), aa = Vec<u32>);
    let mut l = 0;
    let mut r = 1_000_000_001;
    while r - l > 1 {
        let mid = (r+l) / 2;
        if is_ans_ge(mid, &aa) {
            l = mid;
        } else {
            r = mid;
        }
    }
    println!("{}", l);
}