转化为前缀和,变成一道树状数组or线段树的题目,树状数组写起来比较简单,由于t很大,我们将其离散化,细节和注意点在代码中注释。
注意开long long
前缀和要保存sum[0],表示前缀什么都没有。
#include<bits/stdc++.h>
#define lowbit(x) ((x)&(-(x)))
#define ll long long
#define INF 2147483647
#define CLR(a) memset(a, 0, sizeof(a))
using namespace std;
const int maxn=2e5+10;
ll n,t,cnt;
ll a[maxn],sum[maxn];
ll tmp[maxn],tree[maxn];
void add(ll x,ll val){
for(int i=x;i<=maxn;i+=lowbit(i)){
tree[i]+=val;
}
}
ll query(ll x){
ll ans=0;
for(int i=x;i>0;i-=lowbit(i)){
ans+=tree[i];
}
return ans;
}
ll get_id(ll x){
return lower_bound(tmp+1,tmp+1+cnt,x)-tmp;
}
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];
tmp[i]=sum[i];
}
sort(tmp+1,tmp+2+n);//增加tmp[n+1]=0;
cnt=unique(tmp+1,tmp+2+n)-tmp-1;
for(int i=0;i<=n;i++) sum[i]=get_id(sum[i]);
ll ans=0;
add(sum[0],1);//预先加,方便以后操作
for(int i=1;i<=n;i++){
int pos=get_id(tmp[sum[i]]-t);
if(tmp[pos]!=tmp[sum[i]]-t) pos--;//细节关键点,pos是>=的第一个数
ans+=i-query(pos); //取>时要-1进行查询,取=时,不用减
add(sum[i],1);
}
printf("%lld\n",ans);
return 0;
}