Problem:
Score : 500 points

Problem Statement

Given are a sequence of N positive integers A_1, A_2, \ldots, A_N, and a positive integer K.

Find the number of non-empty contiguous subsequences in A such that the remainder when dividing the sum of its elements by K is equal to the number of its elements. We consider two subsequences different if they are taken from different positions, even if they are equal sequences.

Constraints

All values in input are integers.

1 \leq N \leq 2\times 10^5

1 \leq K \leq 10^9

1 \leq A_i \leq 10^9

Input

Input is given from Standard Input in the following format:

N K
A_1 A_2 \cdots A_N

Output

Print the number of subsequences that satisfy the condition.

Sample Input 1

5 4
1 4 2 3 5

Sample Output 1

4

Four sequences satisfy the condition: (1), (4,2), (1,4,2), and (5).

Sample Input 2

8 4
4 2 4 2 4 2 4 2

Sample Output 2

7

(4,2) is counted four times, and (2,4) is counted three times.

Sample Input 3

10 7
14 15 92 65 35 89 79 32 38 46

Sample Output 3

8

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 ! chmax { ( $ x : expr , $ ( $ v : expr ) ,+ ) => { $ ( $ x = std :: cmp :: max ( $ x ,$ v ) ; ) + } ; }
#[macro_export]
macro_rules ! chmin { ( $ x : expr , $ ( $ v : expr ) ,+ ) => { $ ( $ x = std :: cmp :: min ( $ x ,$ v ) ; ) + } ; }
#[macro_export]
macro_rules ! max { ( $ x : expr ) => ( $ x ) ; ( $ x : expr , $ ( $ xs : expr ) ,+ ) => { std :: cmp :: max ( $ x , max ! ( $ ( $ xs ) ,+ ) ) } ; }
#[macro_export]
macro_rules ! min { ( $ x : expr ) => ( $ x ) ; ( $ x : expr , $ ( $ xs : expr ) ,+ ) => { std :: cmp :: min ( $ x , min ! ( $ ( $ xs ) ,+ ) ) } ; }
#[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() {
    let out = stdout();
    let mut out = BufWriter::new(out.lock());

    input!{
        n:usize,k:i64,
        a:[i64;n],
    }

    let mut cum1 = CumSum1::new(n);
    for i in 0..n {
        cum1.set(i,a[i]);
    }
    cum1.build();

    let mut v = vec![0;n+1];
    for i in 0..n {
        let x = cum1.query(0, i+1);
        v[i+1] = (x - (i+1) as i64) % k;
    }

    let mut wm = WMI::new(v.clone());
    let mut cnt = 0;
    for j in 1..n+1 {
        let x = v[j];
        let l = max(0, j as i64 + 1 - k) as usize;
        let r = j;
        cnt += wm.rangefreq(l, r, x, x+1);
    }
    println!("{}", cnt);
}

struct CumSum1 {
    base: Vec<i64>,
    dp: Vec<i64>,
}
impl CumSum1 {
    fn new(n: usize) -> CumSum1 {
        CumSum1 {
            base: vec![0; n],
            dp: vec![],
        }
    }
    fn add(&mut self, i: usize, x: i64) {
        self.base[i] += x;
    }
    fn set(&mut self, i: usize, x: i64) {
        self.base[i] = x;
    }
    fn build(&mut self) {
        let n = self.base.len();
        let mut dp = vec![0; n + 1];
        let mut acc = 0;
        for i in 0..n {
            acc += self.base[i];
            dp[i + 1] = acc;
        }
        self.dp = dp;
    }
    #[doc = "[i,j)"]
    fn query(&self, i: usize, j: usize) -> i64 {
        self.dp[j] - self.dp[i]
    }
}

#[doc = "lower,upper are inclusive range"]
pub struct BinarySearch<F> {
    pub p: F,
    pub lower: i64,
    pub upper: i64,
}
impl<F: Fn(i64) -> bool> BinarySearch<F> {
    #[doc = "O(log(upper-lower))"]
    pub fn lower_bound(&self) -> i64 {
        let lower = self.lower;
        let upper = self.upper;
        assert!(lower <= 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 FID {
    fn popcount(x: u64) -> usize {
        u64::count_ones(x) as usize
    }
    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],
            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
    }
    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);
        }
        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];
            let ns = fid.rank1(s);
            let ne = fid.rank1(e);
            let n1 = ne - ns;
            if n1 >= k {
                res |= msb;
                s = ns;
                e = ne;
                s += self.nzeros[d];
                e += self.nzeros[d];
            } else {
                s = s - ns;
                e = e - ne;
                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 << 62;
        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)
    }
}