佩蒂亚和阵列

题目描述

佩蒂亚有一个阵列和 �n 个整数。他最近学会了区间和,现在他可以非常快速地计算数组任何区间的元素总和。

现在,他想知道他的数组中总和小于 �t 的区间数量是多少?

更确切地说,你需要计算满足 ��+��+1+⋯+��−1+��<�a​l​​+a​l+1​​+⋯+a​r−1​​+a​r​​<t 的数对 (l,r) 的数量

输入描述

第一行包含两个整数 �n 和 �t (1≤�≤2×1051≤n≤2×10​5​​,∣�∣≤2×1014∣t∣≤2×10​14​​)

第二行包含一个整数序列 �1a​1​​ 到 ��a​n​​( ∣��∣≤109∣a​i​​∣≤10​9​​ ),—对 Petya 数组的描述。请注意,可能存在负元素、零元素和正元素。

输出描述

Petya 数组中的段数,元素之和小于 �t.

输入样例1


  1. 5 4
  2. 5 -1 3 4 -1

输出样例1


  1. 5

输入样例2


  1. 3 0
  2. -1 2 -3

输出样例2


  1. 4

输入样例3


  1. 4 -1
  2. -2 1 -2 3

输出样例3


  1. 3

代码


#include<bits/stdc++.h>
using namespace std;
long long n,t,a[400005],ans,cnt,c[400005];
vector<long long>v;
int lowbit(int t){ return t&(-t);}
void update (int x,int y){
    for(int i=x;i<=2*n+1;i+=lowbit(i)) c[i]+=y;
}
long long  getsum (int x){
    long long ans=0;
    for(int i=x;i;i-=lowbit(i)) ans+=c[i];
    return ans;
}
int Find(long long x){
    return int(lower_bound(v.begin(),v.end(),x)-v.begin()+1);
}                                                                                                 
int main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin>>n>>t;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        a[i]+=a[i-1];
        a[n+i]=a[i]+t;
        v.push_back(a[i]);
        v.push_back(a[n+i]);
    }
    v.push_back(t);
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    for(int i=1;i<=n*2;i++)  a[i]=Find(a[i]);
    update(Find(t),1);
    cnt=v.size();
    for(int i=1;i<=n;i++){
        ans+=getsum(cnt)-getsum(a[i]);
        //cout<<getsum(cnt)<<endl;
        update(a[i+n],1);
    }
    cout<<ans;
    return  0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值