欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Codeforces Round #510 (Div. 2) D. Petya and Array

程序员文章站 2022-05-09 15:07:20
...

Codeforces Round #510 (Div. 2) D. Petya and Array

题目链接

Petya has an array a consisting of n integers. He has learned partial sums recently, and now he can calculate the sum of elements on any segment of the array really fast. The segment is a non-empty sequence of elements standing one next to another in the array.

Now he wonders what is the number of segments in his array with the sum less than t. Help Petya to calculate this number.

More formally, you are required to calculate the number of pairs l,r (l≤r) such that a l + a l + 1 + ⋯ + a r < t a_l+a_{l+1}+\cdots+a_r<t al+al+1++ar<t.

Input

The first line contains two integers n and t (1≤n≤200000,|t|≤2e14).

The second line contains a sequence of integers a1,a2,…,an (|ai|≤1e9) — the description of Petya’s array. Note that there might be negative, zero and positive elements.

Output

Print the number of segments in Petya’s array with the sum of elements less than t.

Examples

input

5 4
5 -1 3 4 -1

output

5

input

3 0
-1 2 -3

output

4

input

4 -1
-2 1 -2 3

output

3

题意非常简单,找 1-n 内有多少个区间的和小于 t t t,我们稍加转化:
a l + a l + 1 + ⋯ + a r < t a_l+a_{l+1}+\cdots+a_r<t al+al+1++ar<t
则:
s u m [ r ] − s u m [ l − 1 ] < t sum[r]-sum[l-1]<t sum[r]sum[l1]<t
s u m [ r ] − s u m [ l − 1 ] ≤ t − 1 sum[r]-sum[l-1]\leq t-1 sum[r]sum[l1]t1
s u m [ r ] ≤ s u m [ l − 1 ] + t − 1 sum[r]\leq sum[l-1]+t-1 sum[r]sum[l1]+t1
可以预处理出前缀和,题目就转化为对某个数 x x x,找小于等于 x + t − 1 x+t-1 x+t1 的元素个数,快速找区间内小于等于某个数的个数很容易想到权值线段树,这题因为数据量的问题必须要离散化,用一个 v e c t o r vector vector 存所有前缀和,那么每个前缀和的下标就是他们离散后在线段树中的下标,那么题目就是对每一个前缀和查询符合条件的前缀和个数即可。注意 v e c t o r vector vector 中的元素必须去重,因为权值线段树保留了上一次插入的状态,如果不去重答案会有重复,AC代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+5;
int n,m,k;
ll t,a[N],sum[N],tree[N<<2];
vector<ll>v;
int getpos(ll x){
    return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
void pushup(int i)
{
    tree[i]=tree[i<<1]+tree[i<<1|1];
}

void build(int i,int l,int r)
{
    if(l==r)
    {
        tree[i]=0;
        return ;
    }
    int mid=l+r>>1;
    build(i<<1,l,mid);
    build(i<<1|1,mid+1,r);
    pushup(i);
}

void update(int i,int l,int r,int x,int k)
{
    if(l==r)
    {
        tree[i]+=k;
        return ;
    }
    int mid=l+r>>1;
    if(x<=mid) update(i<<1,l,mid,x,k);
    else update(i<<1|1,mid+1,r,x,k);
    pushup(i);
}

ll query(int i,int l,int r,int m,int n)
{
    if(m<=l&&r<=n) return tree[i];
    int mid=l+r>>1;
    ll ans=0;
    if(m<=mid) ans+=query(i<<1,l,mid,m,n);
    if(n>mid) ans+=query(i<<1|1,mid+1,r,m,n);
    return ans;
}

int main(){
    scanf("%d%lld",&n,&t);
    v.push_back(t-1);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        sum[i]=sum[i-1]+a[i];
        v.push_back(sum[i]);
        v.push_back(sum[i]+t-1);
    }
    if(n==1){
        if(a[1]<t) printf("1");
        else printf("0");
    }else{
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        m=v.size();
        build(1,1,m);
        ll ans=0;
        for(int i=n;i>=0;i--){
            ans+=query(1,1,m,1,getpos(sum[i]+t-1));
            update(1,1,m,getpos(sum[i]),1);
        }
        printf("%lld\n",ans);
    }
    return 0;
}