Problem:
Score : 600 points

Problem Statement

You are given an integer sequence of length N, a = {a_1, a_2, …, a_N}, and an integer K.

a has N(N+1)/2 non-empty contiguous subsequences, {a_l, a_{l+1}, …, a_r} (1 ≤ l ≤ r ≤ N). Among them, how many have an arithmetic mean that is greater than or equal to K?

Constraints

All input values are integers.

1 ≤ N ≤ 2 \times 10^5

1 ≤ K ≤ 10^9

1 ≤ a_i ≤ 10^9

Input

Input is given from Standard Input in the following format:

N K
a_1
a_2
:
a_N

Output

Print the number of the non-empty contiguous subsequences with an arithmetic mean that is greater than or equal to K.

Sample Input 1

3 6
7
5
7

Sample Output 1

5

All the non-empty contiguous subsequences of a are listed below:

{a_1} = {7}

{a_1, a_2} = {7, 5}

{a_1, a_2, a_3} = {7, 5, 7}

{a_2} = {5}

{a_2, a_3} = {5, 7}

{a_3} = {7}

Their means are 7, 6, 19/3, 5, 6 and 7, respectively, and five among them are 6 or greater. Note that {a_1} and {a_3} are indistinguishable by the values of their elements, but we count them individually.

Sample Input 2

1 2
1

Sample Output 2

0

Sample Input 3

7 26
10
20
30
40
30
20
10

Sample Output 3

13

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Linq;
using static System.Math;

class Program
{
    static int N;
    static int K;
    static long[] a;
    static long[] b;

    static void Main()
    {
        /* 入力の受け取り */
        int[] input = Console.ReadLine().Split().Select(int.Parse).ToArray();
        N = input[0];
        K = input[1];
        a = new long[N];
        for (int i = 0; i < N; i++)
            a[i] = long.Parse(Console.ReadLine());

        /* b[i] = a[i] - Kとシフト */
        b = a.Select(s => s - K).ToArray();

        /* bの累積和 */
        long[] sum = new long[N + 1];
        for (int i = 0; i < N; i++)
            sum[i + 1] = sum[i] + b[i];

        /* 累積和の転倒数をN(N+1)/2から引いたものが答え */
        long ans = N * (N + 1) / 2;
        ans -= InvNum.InversionNumber(sum);
        Console.WriteLine(ans);
    }
}

static class InvNum
{
    /* 配列aの転倒数を求める */
    public static long InversionNumber(long[] a)
    {
        int n = a.Length;
        SortedSet<long> s = new SortedSet<long>();
        foreach (var i in a) s.Add(i);
        long[] sorted_a = s.ToArray();
        RSQ1 rsq = new RSQ1(n);
        long[] t2 = new long[n];
        for (int j = 0; j < n; j++)
        {
            t2[j] = rsq.Query(0, BS.Search(sorted_a, a[j]) + 1);
            rsq[BS.Search(sorted_a, a[j])] += 1;
        }
        long InvN = 0;
        for (int j = 0; j < n; j++)
            InvN += j - t2[j];
        return InvN;
    }
    public static long InversionNumber(int[] a)
    {
        long[] a2 = a.Select(s => (long)s).ToArray();
        return InversionNumber(a2);
    }
}

class BS
{
    /* 昇順なarrayからsを二分探索で探し、indexを返す(複数あればそのうちの1つ) */
    public static int Search(long[] array, long s)
    {
        int l = 0;
        int r = array.Length - 1;
        while (l != r)
        {
            int m = l + (r - l) / 2;
            if (array[m] == s) return m;
            if (array[m] < s) l = m + 1;
            if (array[m] > s) r = m - 1;
        }
        return l;
    }
    public static int Search(int[] array, int s)
    {
        long[] lis = array.Select(n => (long)n).ToArray();
        return Search(lis, s);
    }
    public static int Search(List<int> list, int s)
    {
        int[] array = list.ToArray();
        return Search(array, s);
    }
    public static int Search(List<long> list, long s)
    {
        long[] array = list.ToArray();
        return Search(array, s);
    }

    /* 単調非減少なarrayから、array[i] >= kなる最小のiを返す(なければn) */
    public static int Lower_Bound(long[] array, long k)
    {
        int l = -1;
        int r = array.Length;
        while (r - l > 1)
        {
            int m = (l + r) / 2;
            if (array[m] >= k) r = m;
            else l = m;
        }
        return r;
    }
    public static int Lower_Bound(int[] array, int k)
    {
        long[] a = array.Select(s => (long)s).ToArray();
        return Lower_Bound(a, k);
    }
    public static int Lower_Bound(List<long> list, long k)
    {
        long[] a = list.ToArray();
        return Lower_Bound(a, k);
    }
    public static int Lower_Bound(List<int> list, int k)
    {
        int[] a = list.ToArray();
        return Lower_Bound(a, k);
    }
}

struct RSQ1
{
    private int n;
    private long[] dat;
    public int Length { get; private set; }
    public long this[int i]
    {
        get
        {
            if (i < 0 || i >= this.Length)
                throw new IndexOutOfRangeException();
            return dat[i + n - 1];
        }
        set { this.Update(i, value); }
    }

    /* nを要素数として、すべて0で初期化 */
    public RSQ1(int n)
    {
        Length = n;
        this.n = 1;
        while (this.n < n) this.n *= 2;
        dat = new long[2 * this.n];
    }

    /* k番目(0-indexed)をaに変更 */
    public void Update(int k, long a)
    {
        k += n - 1;
        dat[k] = a;
        while (k > 0)
        {
            k = (k - 1) / 2;
            dat[k] = dat[k * 2 + 1] + dat[k * 2 + 2];
        }
    }

    private long Query_(int a, int b, int k, int l, int r)
    {
        if (r <= a || b <= l) return 0;
        if (a <= l && r <= b) return dat[k];
        long v1 = Query_(a, b, k * 2 + 1, l, (l + r) / 2);
        long v2 = Query_(a, b, k * 2 + 2, (l + r) / 2, r);
        return v1 + v2;
    }

    /* [a,b)の和を求める */
    public long Query(int a, int b)
    {
        return Query_(a, b, 0, 0, n);
    }
}