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 Rust (1.15.1) (judge verdict: Accepted)

#[doc = " https://github.com/hatoo/competitive-rust-snippets"]
#[allow(unused_imports)]
use std::cmp::{max, min, Ordering};
#[allow(unused_imports)]
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
#[allow(unused_imports)]
use std::io::{stdin, stdout, BufWriter, Write};
#[allow(unused_imports)]
use std::iter::FromIterator;
#[macro_export]
macro_rules ! dvec { ( $ t : expr ; $ len : expr ) => { vec ! [ $ t ; $ len ] } ; ( $ t : expr ; $ len : expr , $ ( $ rest : expr ) ,* ) => { vec ! [ dvec ! ( $ t ; $ ( $ rest ) ,* ) ; $ len ] } ; }
#[allow(unused_macros)]
macro_rules ! debug { ( $ ( $ a : expr ) ,* ) => { eprintln ! ( concat ! ( $ ( stringify ! ( $ a ) , " = {:?}, " ) ,* ) , $ ( $ a ) ,* ) ; } }
#[macro_export]
macro_rules ! input { ( source = $ s : expr , $ ( $ r : tt ) * ) => { let mut parser = Parser :: from_str ( $ s ) ; input_inner ! { parser , $ ( $ r ) * } } ; ( parser = $ parser : ident , $ ( $ r : tt ) * ) => { input_inner ! { $ parser , $ ( $ r ) * } } ; ( new_stdin_parser = $ parser : ident , $ ( $ r : tt ) * ) => { let stdin = std :: io :: stdin ( ) ; let reader = std :: io :: BufReader :: new ( stdin . lock ( ) ) ; let mut $ parser = Parser :: new ( reader ) ; input_inner ! { $ parser , $ ( $ r ) * } } ; ( $ ( $ r : tt ) * ) => { input ! { new_stdin_parser = parser , $ ( $ r ) * } } ; }
#[macro_export]
macro_rules ! input_inner { ( $ parser : ident ) => { } ; ( $ parser : ident , ) => { } ; ( $ parser : ident , $ var : ident : $ t : tt $ ( $ r : tt ) * ) => { let $ var = read_value ! ( $ parser , $ t ) ; input_inner ! { $ parser $ ( $ r ) * } } ; }
#[macro_export]
macro_rules ! read_value { ( $ parser : ident , ( $ ( $ t : tt ) ,* ) ) => { ( $ ( read_value ! ( $ parser , $ t ) ) ,* ) } ; ( $ parser : ident , [ $ t : tt ; $ len : expr ] ) => { ( 0 ..$ len ) . map ( | _ | read_value ! ( $ parser , $ t ) ) . collect ::< Vec < _ >> ( ) } ; ( $ parser : ident , chars ) => { read_value ! ( $ parser , String ) . chars ( ) . collect ::< Vec < char >> ( ) } ; ( $ parser : ident , usize1 ) => { read_value ! ( $ parser , usize ) - 1 } ; ( $ parser : ident , $ t : ty ) => { $ parser . next ::<$ t > ( ) . expect ( "Parse error" ) } ; }
use std::io;
use std::io::BufRead;
use std::str;
pub struct Parser<R> {
    reader: R,
    buf: Vec<u8>,
    pos: usize,
}
impl Parser<io::Empty> {
    pub fn from_str(s: &str) -> Parser<io::Empty> {
        Parser {
            reader: io::empty(),
            buf: s.as_bytes().to_vec(),
            pos: 0,
        }
    }
}
impl<R: BufRead> Parser<R> {
    pub fn new(reader: R) -> Parser<R> {
        Parser {
            reader: reader,
            buf: vec![],
            pos: 0,
        }
    }
    pub fn update_buf(&mut self) {
        self.buf.clear();
        self.pos = 0;
        loop {
            let (len, complete) = {
                let buf2 = self.reader.fill_buf().unwrap();
                self.buf.extend_from_slice(buf2);
                let len = buf2.len();
                if len == 0 {
                    break;
                }
                (len, buf2[len - 1] <= 0x20)
            };
            self.reader.consume(len);
            if complete {
                break;
            }
        }
    }
    pub fn next<T: str::FromStr>(&mut self) -> Result<T, T::Err> {
        loop {
            let mut begin = self.pos;
            while begin < self.buf.len() && (self.buf[begin] <= 0x20) {
                begin += 1;
            }
            let mut end = begin;
            while end < self.buf.len() && (self.buf[end] > 0x20) {
                end += 1;
            }
            if begin != self.buf.len() {
                self.pos = end;
                return str::from_utf8(&self.buf[begin..end]).unwrap().parse::<T>();
            } else {
                self.update_buf();
            }
        }
    }
}
#[allow(unused_macros)]
macro_rules ! debug { ( $ ( $ a : expr ) ,* ) => { eprintln ! ( concat ! ( $ ( stringify ! ( $ a ) , " = {:?}, " ) ,* ) , $ ( $ a ) ,* ) ; } }
#[doc = " https://github.com/hatoo/competitive-rust-snippets"]
const BIG_STACK_SIZE: bool = true;
#[allow(dead_code)]
fn main() {
    use std::thread;
    if BIG_STACK_SIZE {
        thread::Builder::new()
            .stack_size(32 * 1024 * 1024)
            .name("solve".into())
            .spawn(solve)
            .unwrap()
            .join()
            .unwrap();
    } else {
        solve();
    }
}
fn solve() {
    input!{
        n:usize,k:i64,
        a:[i64;n]
    }
    let mut b = vec![];
    for i in 0..n {
        b.push(a[i]-k);
    }
    for i in 1..n {
        b[i] += b[i-1]
    }
    let wm = WMI::new(b.clone());
    let mut cnt = 0;
    for i in 0..n {
        // [i,n)の中にb[i]以上のものはいくつあるか？
        cnt += wm.rangefreq(i, n, b[i], 1<<61);
        // もし自分が負だったら自分は含まない
        if b[i] < 0 {
            cnt -= 1;
        }
    }
    println!("{}", cnt);
}
#[doc = "lower,upper are inclusive range"]
struct BinarySearch<F> {
    p: F,
    lower: i64,
    upper: i64,
}
impl<F: Fn(i64) -> bool> BinarySearch<F> {
    #[doc = "O(log(upper-lower))"]
    fn lower_bound(&self) -> i64 {
        let lower = self.lower;
        let upper = self.upper;
        let mut lb = lower - 1;
        let mut ub = upper + 1;
        while ub - lb > 1 {
            let mid = (lb + ub) / 2;
            if (self.p)(mid) {
                ub = mid;
            } else {
                lb = mid;
            }
        }
        let latter = ub;
        latter
    }
}
#[derive(Clone)]
struct FID {
    n: usize,
    n_blocks: usize,
    blocks: Vec<u64>,
    block_rank1: Vec<usize>,
}
// impl std::fmt::Debug for FID {
//     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
//         let mut s = String::new();
//         let n = self.n;
//         for i in 0..n {
//             if self.access(i) {
//                 s.push('1');
//             } else {
//                 s.push('0');
//             }
//         }
//         write!(f, "{}", s)
//     }
// }
impl FID {
    // O(1)
    fn popcount(x: u64) -> usize {
        u64::count_ones(x) as usize
    }
    // O(64)
    fn kpopi(x: u64, k: usize) -> usize {
        let mut x = x;
        let mut k = k;
        let mut ans = 64;
        for i in 0..64 {
            if x & (1<<i) > 0 {
                k -= 1;
            }
            if k == 0 {
                ans = i;
                break;
            }
        }
        ans
    }
    pub fn new(n: usize) -> FID {
        let n_blocks = (n>>6)+1;
        FID {
            n: n,
            n_blocks: (n>>6)+1,
            blocks: vec![0; n_blocks],
            // blocks[0,i)の1の数
            block_rank1: vec![0; n_blocks],
        }
    }
    pub fn set(&mut self, k: usize) {
        self.blocks[k>>6] |= 1<<(k&0b111111);
    }
    pub fn build(&mut self) {
        self.block_rank1[0] = 0;
        // 累積和
        for i in 1..self.n_blocks {
            self.block_rank1[i] = self.block_rank1[i-1] + Self::popcount(self.blocks[i-1]);
        }
    }
    pub fn access(&self, k: usize) -> bool {
        let x = self.blocks[k>>6] & 1<<(k&0b111111);
        if x > 0 { true } else { false }
    }
    #[doc = "count 1s in [0,k)"]
    pub fn rank1(&self, k: usize) -> usize {
        let mask = (1<<(k&0b111111)) - 1;
        let rest = self.blocks[k>>6] & mask;
        self.block_rank1[k>>6] + Self::popcount(rest)
    }
    #[doc = "count 0s in [0,k). O(1)"]
    pub fn rank0(&self, k: usize) -> usize {
        k - self.rank1(k)
    }
    pub fn rank(&self, b: bool, k: usize) -> usize {
        if b {
            self.rank1(k)
        } else {
            self.rank0(k)
        }
    }
    #[doc = "query the index of k-th 0 (0-indexed)"]
    pub fn select0(&self, k: usize) -> usize {
        let bs = BinarySearch {
            lower: 0,
            upper: (self.n-1) as i64,
            p: |i: i64| {
                let r = self.rank0(i as usize);
                r >= k+1
            },
        };
        bs.lower_bound() as usize - 1
    }
    #[doc = "query the index of k-th 1 (0-indexed)"]
    pub fn select1(&self, k: usize) -> usize {
        let bs = BinarySearch {
            lower: 0,
            upper: (self.n-1) as i64,
            p: |i: i64| {
                let r = self.rank1(i as usize);
                r >= k+1
            },
        };
        bs.lower_bound() as usize - 1
    }
    // #[doc = "query the index of k-th 0 (0-indexed)"]
    // pub fn select0_block_jump(&self, k: usize) -> usize {
    //     let mut remaining = k+1;
    //     let bs = BinarySearch {
    //         lower: 0,
    //         upper: (self.n_blocks-1) as i64,
    //         p: |i: i64| {
    //             let i = i as usize;
    //             (i<<6) - self.block_rank1[i] >= remaining
    //         }
    //     };
    //     let l = bs.lower_bound() as usize - 1;
    //     let count0 = (l<<6) - self.block_rank1[l];
    //     remaining -= count0;
    //     assert!(remaining>0);
    //     (l<<6) | Self::kpopi(!self.blocks[l], remaining)
    // }
    // #[doc = "query the index of k-th 1 (0-indexed)"]
    // pub fn select1_block_jump(&self, k: usize) -> usize {
    //     let mut remaining = k+1; // remaining
    //     let bs = BinarySearch {
    //         lower: 0,
    //         upper: (self.n_blocks-1) as i64,
    //         p: |i: i64| {
    //             let i = i as usize;
    //             self.block_rank1[i] >= remaining
    //         },
    //     };
    //     let l = bs.lower_bound() as usize - 1;
    //     let count1 = self.block_rank1[l];
    //     remaining -= count1;
    //     assert!(remaining>0);
    //     (l<<6) | Self::kpopi(self.blocks[l], remaining)
    // }
    pub fn select(&self, b: bool, k: usize) -> usize {
        if b {
            self.select1(k)
        } else {
            self.select0(k)
        }
    }
}

struct WM {
    mat: Vec<FID>,
    nzeros: Vec<usize>,
}
impl WM {
    pub fn new(xs: Vec<u64>) -> WM {
        let n = xs.len();
        let mut mat = vec![];
        let mut nzeros = vec![];
        let mut cur = xs;
        for i in 0..64 {
            let mid = 1<<(63-i);
            let mask = mid - 1;
            let mut b = vec![];
            let mut left = vec![];
            let mut right = vec![];
            for i in 0..n {
                let x = cur[i];
                if x >= mid {
                    right.push(x & mask);
                    b.push(true);
                } else {
                    left.push(x & mask);
                    b.push(false);
                }
            }
            nzeros.push(left.len());

            left.append(&mut right);
            cur = left;
            let mut fid = FID::new(n);
            for i in 0..n {
                if b[i] {
                    fid.set(i);
                }
            }
            fid.build();
            mat.push(fid);
        }
        // dbg!(&nzeros);
        // dbg!(&mat);

        WM {
            mat: mat,
            nzeros: nzeros,
        }
    }
    #[doc = "counting x in v[0,i) O(1)"]
    pub fn rank(&self, x: u64, i: usize) -> usize {
        let mut s = 0;
        let mut e = i;
        for d in 0..64 {
            let fid = &self.mat[d];
            let b = x & (1<<(63-d)) > 0;
            s = fid.rank(b, s);
            e = fid.rank(b, e);
            if b {
                s += self.nzeros[d];
                e += self.nzeros[d];
            }
        }
        e-s
    }
    #[doc = "the position of k-th x (0-indexed). O(logn)"]
    pub fn select(&self, x: u64, k: usize) -> usize {
        let bs = BinarySearch {
            lower: 0,
            upper: (self.mat[0].n - 1) as i64,
            p: |i: i64| {
                let cnt = self.rank(x, i as usize);
                cnt >= k+1
            },
        };
        bs.lower_bound() as usize - 1
    }
    #[doc = "k-th largest number in [l,r)"]
    pub fn quantile(&self, l: usize, r: usize, k: usize) -> u64 {
        let mut res = 0;
        let mut k = k;
        let mut s = l;
        let mut e = r;
        for d in 0..64 {
            let msb = 1<<(63-d);
            let fid = &self.mat[d];
            // dbg!((s,e));
            let ns = fid.rank1(s);
            let ne = fid.rank1(e);
            // dbg!((&fid,k,d,s,e,ns,ne));
            let n1 = ne-ns;
            if n1 >= k { // right
                res |= msb;
                s = ns;
                e = ne;
                s += self.nzeros[d];
                e += self.nzeros[d];
            } else { // left
                // rank0(k)+rank1(k)=k
                s = s - ns;
                e = e - ne;
                // 1側にn1個あるから、0側で大きい方k-n1個を探す
                k -= n1;
            }
        }
        res 
    }
    pub fn rank_all(&self, l: usize, r: usize, x: u64) -> (usize, usize, usize) {
        let mut cnt_lt = 0;
        let mut cnt_gt = 0;
        let mut s = l;
        let mut e = r;
        
        for d in 0..64 {
            let b = x & (1<<(63-d)) > 0;
            let lcnt = self.mat[d].rank(b, s);
            let rcnt = self.mat[d].rank(b, e);
            let add = (e-s) - (rcnt-lcnt);
            if b {
                cnt_lt += add;
            } else {
                cnt_gt += add;
            }
            s = lcnt;
            e = rcnt;
            if b {
                s += self.nzeros[d];
                e += self.nzeros[d];
            }
        }

        (cnt_lt, e-s, cnt_gt)
    }
    #[doc = "counting numbers in range [min,max) in v[l,r). O(1)"]
    pub fn rangefreq(&self, l: usize, r: usize, min: u64, max: u64) -> usize {
        let (cntlt_max,_,_) = self.rank_all(l, r, max);
        let (cntlt_min,_,_) = self.rank_all(l, r, min);
        cntlt_max - cntlt_min
    }
}

struct WMI {
    offset: i64,
    wm: WM,
}
impl WMI {
    pub fn new(xs: Vec<i64>) -> WMI {
        let offset = 1<<61;
        let mut ys = vec![];
        for x in xs {
            ys.push((x+offset) as u64)
        }
        let wm = WM::new(ys);
        WMI {
            offset: offset,
            wm: wm
        }
    }
    pub fn rangefreq(&self, l: usize, r: usize, min: i64, max: i64) -> usize {
        self.wm.rangefreq(l, r, (min+self.offset) as u64 , (max+self.offset) as u64)
    }
    pub fn quantile(&self, l: usize, r: usize, k: usize) -> i64 {
        self.wm.quantile(l, r, k) as i64 - self.offset
    }
    pub fn rank(&self, x: i64, i: usize) -> usize {
        self.wm.rank((x+self.offset) as u64, i)
    }
    pub fn select(&self, x: i64, k: usize) -> usize {
        self.wm.select((x+self.offset) as u64, k)
    }
}