思路:
树状数组+离散化
条件可转化为
p
r
e
[
r
]
−
p
r
e
[
l
−
1
]
<
t
pre[r]-pre[l-1]<t
pre[r]−pre[l−1]<t,即
p
r
e
[
r
]
−
t
<
p
r
e
[
l
−
1
]
pre[r]-t<pre[l-1]
pre[r]−t<pre[l−1],这就转化为一个类似二维偏序的东西。
l
−
1
l-1
l−1的取值范围
[
0
,
r
−
1
]
[0,r-1]
[0,r−1],即对每一个
p
r
e
[
r
]
pre[r]
pre[r]都查找这个范围里的
p
r
e
[
]
pre[]
pre[]大于
p
r
e
[
r
]
−
t
pre[r]-t
pre[r]−t的个数有多少个。
建立树状数组,从左到右将
p
r
e
[
i
]
pre[i]
pre[i]依次插入到树状数组中,插入之前首先对未查出状态进行查找,将合法个数加入答案。
注意
l
−
1
l-1
l−1的范围是
[
0
,
r
−
1
]
[0,r-1]
[0,r−1],
p
r
e
[
0
]
=
0
pre[0]=0
pre[0]=0,要提前插入到树状数组中。
因为
p
r
e
[
]
pre[]
pre[]数组较大,我们首先将其离散化。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
ll c[maxn];
int lowbit(int x){
return x&(-x);
}
void add(int x,int d){
while(x<=200005){
c[x]+=d;x+=lowbit(x);
}
}
ll sum(int x){
ll ans=0;
while(x>0){
ans+=c[x];x-=lowbit(x);
}
return ans;
}
int n;
ll t,a[maxn],pre[maxn],lsh[maxn];
int main(){
scanf("%d%lld",&n,&t);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
pre[i]=pre[i-1]+a[i];
lsh[i]=pre[i];
}
lsh[n+1]=0;
sort(lsh+1,lsh+1+n+1);
int m=unique(lsh+1,lsh+1+n+1)-lsh-1;
int tmp=lower_bound(lsh+1,lsh+1+n+1,0)-lsh;
add(tmp,1);
ll ans=0;
for(int i=1;i<=n;i++){
int k=upper_bound(lsh+1,lsh+1+n+1,pre[i]-t)-lsh;
ans+=i-sum(k-1);
k=lower_bound(lsh+1,lsh+1+n+1,pre[i])-lsh;
add(k,1);
}
printf("%lld\n",ans);
}