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: Accepted)

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
class Solve{
    public Solve(){}
    StringBuilder sb;
    public static int Main(){
        new Solve().Run();
        return 0;
    }
    void Run(){
        sb = new StringBuilder();
        Calc();
        Console.Write(sb.ToString());
    }
    void Calc(){
        string[] str = Console.ReadLine().Split(' ');
        int N = int.Parse(str[0]);
        long K = int.Parse(str[1]);
        long[] A = new long[N];
        for(int i=0;i<N;i++){
            A[i] = int.Parse(Console.ReadLine()) - K;
        }
        N++;
        long[] sum = new long[N];
        for(int i=1;i<N;i++){
            sum[i] = sum[i-1] + A[i-1];
        }
        long[] B = new long[N];
        int[] C = new int[N];
        for(int i=0;i<N;i++){
            B[i] = sum[i];
            C[i] = i;
        }
        Array.Sort(C,(x,y)=>(B[x] > B[y] ? 1 : (B[x] == B[y] ? (x > y ? 1 : (x == y ? 0 : -1)) : -1)));
        SegTree Seg = new SegTree(N,this);
        long count = 0;
        for(int i=N-1;i>=0;i--){
            
            count += Seg.Sum(C[i],N-1);
            Seg.Add(C[i]);
        }
        sb.Append(count+"\n");
    }
}

struct SegTree{
    Solve Sol;
    public int[] X;
    //葉の最初の場所
    public int segf;
    //segfのbit
    public int segfb;
    //葉の深さの内浅い方
    public int depth;
    //浅い葉の内座標が最大のもの
    public int borderP;
    //はみ出すものの数
    public int border;
    public SegTree(int N,Solve So){
        Sol = So;
        X = new int[2*N-1];
        for(depth = 1;(1 << depth) <= N;depth++){
            ;
        }
        segf = N-1;
        borderP = (1 << depth) - 2;
        border = 2*N - borderP - 2;
        segfb = border/2;
    }
    public int ToBit(int p){
        if(p >= border){
            return segfb + p - border;
        }
        else{
            return p;
        }
    }
    //葉のある場所
    public int ToLeaf(int p){
        if(p >= border){
            return segf + p - border;
        }
        else{
            return borderP + p + 1;
        }
    }
    //葉の示す頂点
    public int ToPoint(int leaf){
        if(leaf > borderP){
            return leaf - borderP - 1;
        }
        else{
            return leaf - segf + border;
        }
    }
    public void Add(int p){
        //葉の作業
        X[ToLeaf(p)]++;
        //親の作業
        for(int v=ToLeaf(p);v!=0;v=(v-1)/2){
            int spa = (v-1)/2;
            X[spa]++;
        }
    }
    //vの子の内bより大きいものに(bは子孫,bはToBitしたもの)
    int More(int b,int v,int depth){
        int count = 0;
        if((b & (1 << depth)) == 0){
            //右の子は全てbより大きい
            if(((b+1) % (1 << depth)) != 0){
                count += More(b,v*2+1,depth-1);
                count += Act(v*2+2);
            }
            else{
                count += Act(v*2+2);
            }
        }
        else{
            //左の子は全てb未満
            count += More(b,v*2+2,depth-1);
        }
        return count;
    }
    //vの子の内bより小さなものに(bは子孫,bはToBitしたもの)
    int Less(int b,int v,int depth){
        int count = 0;
        if((b & (1 << depth)) == 0){
            //右の子は全てbより大きい
            count += Less(b,v*2+1,depth-1);
        }
        else{
            //左の子は全てb未満
            if(b % (1 << depth) != 0){
                count += Act(v*2+1);
                count += Less(b,v*2+2,depth-1);
            }
            else{
                //右の子は全てb以上
                count += Act(v*2+1);
            }
        }
        return count;
    }
    int Section(int bl,int br,int v,int dl,int dr){
        int count = 0;
        if(v >= segf){
            //葉
            count += Act(v);
        }
        else{
            if((bl & (1 << dl)) == 0 && (br & (1 << dr)) == 0){
                //両方左
                count += Section(bl,br,v*2+1,dl-1,dr-1);
            }
            else if((bl & (1 << dl)) != 0 && (br & (1 << dr)) != 0){
                //両方右
                count += Section(bl,br,v*2+2,dl-1,dr-1);
            }
            else{
                //左と右に分かれた
                if(bl % (1 << dl) != 0){
                    count += More(bl-1,v*2+1,dl-1);
                }
                else{
                    //左は全て含まれる
                    count += Act(v*2+1);
                }
                if((br + 1) % (1 << dl) != 0){
                    count += Less(br+1,v*2+2,dr-1);
                }
                else{
                    //右は全て含まれる
                    count += Act(v*2+2);
                }
            }
        }
        return count;
    }
    public int Sum(int l0,int r0){
        int bl = ToBit(l0);
        int br = ToBit(r0);
        int dl = l0 >= border ? depth - 2 : depth - 1;
        int dr = r0 >= border ? depth - 2 : depth - 1;
        return Section(bl,br,0,dl,dr);
    }
    public int Act(int v){
        return X[v];
    }
}