Petya and Array

Petya and Array

Petya has an array aa consisting of nn 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 tt. Help Petya to calculate this number.

More formally, you are required to calculate the number of pairs l,rl,r (l≤rl≤r) such that al+al+1+⋯+ar−1+ar<tal+al+1+⋯+ar−1+ar<t.

Input

The first line contains two integers nn and tt (1≤n≤200000,|t|≤2⋅10141≤n≤200000,|t|≤2⋅1014).

The second line contains a sequence of integers a1,a2,…,ana1,a2,…,an (|ai|≤109|ai|≤109) — 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 tt.

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

Note

In the first example the following segments have sum less than 44:

  • [2,2][2,2], sum of elements is −1−1
  • [2,3][2,3], sum of elements is 22
  • [3,3][3,3], sum of elements is 33
  • [4,5][4,5], sum of elements is 33
  • [5,5][5,5], sum of elements is −1
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <vector>
#include <cstring>
#include <map>
using namespace std;
const int N=2e5+100;
typedef long long LL;
vector<LL>V;
int T[N<<3];
LL res;
LL sum[N];
LL a[N];
LL n,t;

int get_id(LL x)  //离散化处理
{
  return lower_bound(V.begin(),V.end(),x)-V.begin()+1;
}

void BuildTree(int rt,int l,int r)
{
  T[rt]=0;
  if(l==r)return;
  int mid=(l+r)>>1;
  BuildTree(rt<<1,l,mid);
  BuildTree(rt<<1|1,mid+1,r);
}

void Updata(int p,int v,int rt,int l,int r)  //插入v个值为p的数,若v为负数,即为删去.
{
  T[rt]+=v;
  if(l==r)return;
  int mid=(l+r)>>1;
  if(p<=mid)Updata(p,v,rt<<1,l,mid);
  else Updata(p,v,rt<<1|1,mid+1,r);
}


void less_num(int pos,int rt,int l,int r)
{
   if(l==r)
   return;
   int mid=(l+r)>>1;
   if(pos<=mid)
   less_num(pos,rt<<1,l,mid);
   else
   {
     res+=T[rt<<1];
     less_num(pos,rt<<1|1,mid+1,r);
   }
}



int main()
{
    scanf("%lld%lld",&n,&t);
    for(int i=1;i<=n;i++)
    {
      scanf("%lld",&a[i]);
      sum[i]=sum[i-1]+a[i];  // 求前缀和
      V.push_back(sum[i]);   
    }
    if(n==1)
    {
        if(a[1]<t)
        printf("1\n");
        else
        printf("0\n");
        return 0;
    }
    for(int i=1;i<=n;i++)
    {
      LL x=sum[i]+t;
      V.push_back(x);
    }
    sort(V.begin(),V.end());   // 关键一步 ,便于后面的二分查找,在树中的默认比较。
    V.erase(unique(V.begin(),V.end()),V.end());   //  去掉重复的数值。  这步不是很理解,求大
                                                  //  佬指点
    int len=V.size();
    BuildTree(1,1,len);
    Updata(get_id(sum[n]),1,1,1,len);  
    for(int i=n-1;i>=0;i--)   // 从右到左把前缀和在V(vector)中的下标 依次给到树中
    {
       LL x=sum[i]+t;
       less_num(get_id(x),1,1,len);  // 判断 当前 sum[n…i+1]-sum[i] < t 的个数
                                     // 即 a[n]+…+a[i+1] <t 的个数
                                     // 这样做就间接实现了 两重循环的暴力做法O(n^2)
       if(i>0)
       Updata(get_id(sum[i]),1,1,1,len);
    }
    printf("%lld\n",res);
    return 0;
}

 

 

 

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值