考虑枚举 $r$,计算出所有满足题意的 $l$ 的数量。
设 $S$ 为 $A$ 的前缀和数组,若 $L \le S_r - S_l \le R$,则区间 $(l,r]$ 满足题意。
作一个简单的变化就能求出 $S_l$ 的范围:$S_r - R\le S_l\le S_r - L$。
那么我们依次枚举 $1\ldots N$ 作为 $r$,维护 $S_0 \ldots S_{r - 1}$ 即可。
可以使用树状数组+离散化或者动态开点权值线段树,我选择的是树状数组+离散化。
时间复杂度 $O(N\log N)$。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 5;
typedef long long ll;
const int maxm = 4e5 + 5;
int n,cnt;
ll L,R,a[maxn],d[maxm],c[maxm],s[maxn];
int sum[maxm];
int lowbit(int x) {
return x & -x;
}
void add(int x,int y) {
if(!x)return ;
for(;x <= cnt;x += lowbit(x))sum[x] += y;
return ;
}
int query(int x) {
int ans = 0;
for(;x;x -= lowbit(x))ans += sum[x];
return ans;
}
int main() {
scanf("%d%lld%lld",&n,&L,&R);
d[++ cnt] = s[0] = 0;
for(int i = 1;i <= n;++ i) {
scanf("%lld",&a[i]);
s[i] = s[i - 1] + a[i];
d[++ cnt] = s[i];
d[++ cnt] = s[i] - L;
d[++ cnt] = s[i] - R;
}
for(int i = 1;i <= cnt;++ i)c[i] = d[i];
sort(c + 1 , c + 1 + cnt);
cnt = unique(c + 1 , c + 1 + cnt) - c - 1;
for(int i = 1;i <= 3 * n + 1;++ i)d[i] = lower_bound(c + 1 , c + 1 + cnt , d[i]) - c;
add(d[1] , 1);//提前插入 s[0]
ll ans = 0;
for(int i = 1;i <= n;++ i) {
ans += query((int)d[3 * i]) - query((int)d[3 * i + 1] - 1);
add((int)d[3 * i - 1] , 1);
}
printf("%lld",ans);
return 0;
}