就是求 区间和∈[L,R]的区间的个数
求一下前缀和,就是对于每个右端点查询左边 前缀和∈[sum[i]-R , sum[i]-L]的个数
值域线段树瞎搞搞就好
注意值可能为负
还要先插入一个0表示sum[0] = 0 【感谢良心样例
#include<bits/stdc++.h>
#define MAXN 100005
#define INF 10000000000ll
using namespace std; int n;long long ll,rr;
long long sum[MAXN];
struct t1{
int cnt,leftson,rightson;
}dt[MAXN * 85]; int cnt_node = 1 , root = 1;
void insert(int &now,long long l,long long r,long long v){
if(!now) now = ++cnt_node;
++dt[now].cnt;
if(l==r) return ;
long long mid = (l+r)>>1;
if(v<=mid) insert(dt[now].leftson,l,mid,v);
else insert(dt[now].rightson,mid+1,r,v);
}
int inqry(int now,long long l,long long r,long long L,long long R){
if(L<=l&&r<=R) return dt[now].cnt;
long long mid = (l+r)>>1;
int tmp = 0;
if(L<=mid && dt[now].leftson) tmp = inqry(dt[now].leftson,l,mid,L,R);
if(mid<R && dt[now].rightson) tmp += inqry(dt[now].rightson,mid+1,r,L,R);
return tmp;
}
int main(){
// freopen("1.in","r",stdin);
scanf("%d%lld%lld",&n,&ll,&rr);
for(int i=1;i<=n;++i)
scanf("%lld",sum+i),sum[i] += sum[i-1];
long long ans = 0;
insert(root,-INF,INF,0);
for(int i=1;i<=n;++i){
ans += inqry(root,-INF,INF,sum[i]-rr,sum[i]-ll);
insert(root,-INF,INF,sum[i]);
}
printf("%lld",ans);
return 0;
}