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 C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Linq;
using System.Collections.Generic;

namespace Contest
{
    class Program
    {
        static void Main(string[] args)
        {
            ABC107.D();
        }
        
        class ABC107
        {
            public static void A()
            {
                Console.WriteLine(Read.Int() - Read.Int() + 1);
            }
            public static void B()
            {
                var H = Read.Int();
                var W = Read.Int();
                bool[,] A = new bool[H, W];
                for(int i = 0; i < H; ++i)
                {
                    var str = Read.Str();
                    for(int j = 0; j < W; ++j)
                    {
                        A[i, j] = str[j] == '#';
                    }
                }
                var raws = Enumerable.Range(0, H).Where(i => Enumerable.Range(0, W).Any(j => A[i, j])).ToArray();
                var cols = Enumerable.Range(0, W).Where(j => Enumerable.Range(0, H).Any(i => A[i, j])).ToArray();
                foreach(var raw in raws)
                {
                    Console.WriteLine(String.Join("", cols.Select(j => A[raw, j] ? "#" : ".")));
                }
            }
            public static void C()
            {
                var N = Read.Int();
                var K = Read.Int();
                var X = Read.LongN();
                Console.WriteLine(Enumerable.Range(0, N - K + 1).Select(i => X[i + K - 1] - X[i] + Math.Min(Math.Abs(X[i]), Math.Abs(X[i + K - 1]))).Min());
            }
            public static void D()
            {
                var N = Read.Long();
                var A = Read.LongN();
                long min = A.Min();
                long max = A.Max() + 1;
                long hurdle = (N * (N + 1) / 2 + 1) / 2;
                while (min + 1 < max)
                {
                    var mid = (min + max) / 2;
                    var count = D_Median(A, mid);
                    if (count < hurdle)
                    {
                        max = mid;
                    }
                    else
                    {
                        min = mid;
                    }
                }
                Console.WriteLine(min);
            }
            static long D_Median(long[] A, long x)
            {
                var B = new int[A.Length + 1];
                for(int i = 0; i < A.Length; ++i)
                {
                    B[i + 1] = B[i] + (A[i] >= x ? 1 : -1);
                }
                return ((long)A.Length * (A.Length + 1) / 2) - Util.CountInversion_Naive(B);
            }
        }

        class Util
        {
            public static long CountInversion_Naive(int[] array)
            {
                var min = array.Min();
                var max = array.Max();
                var bit = new BIT(max - min + 1);
                long count = 0;
                for (int i = 0; i < array.Length; ++i)
                {
                    var v = array[i] - min + 1;
                    bit.Add(v, 1);
                    count += i + 1 - bit.Sum(v);
                }
                return count;
            }
            public class BIT
            {
                int N; long[] array;
                public BIT(int m) { for (int n = 1; ; n *= 2) { if (n >= m) { N = n; array = new long[N + 1]; break; } } }
                public void Add(int idx, int v) { for (int x = idx; x <= N; x += x & -x) { array[x] += v; } }
                public long Sum(int idx) { long ret = 0; for (int x = idx; x > 0; x -= x & -x) { ret += array[x]; } return ret; }
            }
        }

        static class Read
        {
            static Queue<string> queue = new Queue<string>();
            static void Enqueue() { var ss = Console.ReadLine().Split(' '); foreach (var s in ss) { queue.Enqueue(s); } }
            public static int Int() { if (queue.Count == 0) { Enqueue(); } return Convert.ToInt32(queue.Dequeue()); }
            public static long Long() { if (queue.Count == 0) { Enqueue(); } return Convert.ToInt64(queue.Dequeue()); }
            public static string Str() { if (queue.Count == 0) { Enqueue(); } return queue.Dequeue(); }
            public static int[] IntN() { return Console.ReadLine().Split(' ').Select(s => Convert.ToInt32(s)).ToArray(); }
            public static long[] LongN() { return Console.ReadLine().Split(' ').Select(s => Convert.ToInt64(s)).ToArray(); }
            public static string[] StrN() { return Console.ReadLine().Split(' '); }
            public static Tuple<int, int>[] TupleInt(int n) { List<Tuple<int, int>> list = new List<Tuple<int, int>>(); for (int i = 0; i < n; ++i) { var ab = Read.IntN(); list.Add(new Tuple<int, int>(ab[0], ab[1])); } return list.ToArray(); }
            public static Tuple<long, long>[] TupleLong(int n) { List<Tuple<long, long>> list = new List<Tuple<long, long>>(); for (int i = 0; i < n; ++i) { var ab = Read.LongN(); list.Add(new Tuple<long, long>(ab[0], ab[1])); } return list.ToArray(); }
            public static Tuple<string, string>[] TupleStr(int n) { List<Tuple<string, string>> list = new List<Tuple<string, string>>(); for (int i = 0; i < n; ++i) { var ab = Read.StrN(); list.Add(new Tuple<string, string>(ab[0], ab[1])); } return list.ToArray(); }
            public static Tuple<double, double>[] TupleDouble(int n) { List<Tuple<double, double>> list = new List<Tuple<double, double>>(); for (int i = 0; i < n; ++i) { var ab = Read.LongN(); list.Add(new Tuple<double, double>(ab[0], ab[1])); } return list.ToArray(); }
            public static long[,] LongMatrix(int r, int c)
            {
                var mat = new long[r, c];
                for (int i = 0; i < r; ++i)
                {
                    var x = Read.LongN();
                    for (int j = 0; j < c; ++j)
                    {
                        mat[i, j] = x[j];
                    }
                }
                return mat;
            }
            public static Dictionary<int, HashSet<int>> AdjacencyList(int N, int M)
            {
                Dictionary<int, HashSet<int>> dict = new Dictionary<int, HashSet<int>>();
                for (int i = 0; i <= N; ++i)
                {
                    dict.Add(i, new HashSet<int>());
                }
                for (int i = 0; i < M; ++i)
                {
                    var ab = Read.IntN();
                    dict[ab[0]].Add(ab[1]);
                    dict[ab[1]].Add(ab[0]);
                }
                return dict;
            }
        }
    }
}