题意:求区间长度在[L,R]内,区间和大于等于s的区间个数。
解析:先将所有的前缀和离散化,然后将长度为L到R的前缀逐一插入树状数组,再枚举区间左端点,扫一遍离散化后的前缀和数组,扫的过程中先更新答案,再更新树状数组。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
long long sum[maxn];
long long mp[maxn];
int tree[maxn];
int n,m;
int lowbit(int x)
{
return x&-x;
}
void add(int x,int v)
{
while(x<=m)
{
tree[x]+=v;
x+=lowbit(x);
}
}
int get(int x)
{
int res=0;
while(x)
{
res+=tree[x];
x-=lowbit(x);
}
return res;
}
int main()
{
ios_base::sync_with_stdio(0);
int l,r;
long long s;
cin>>n>>l>>r>>s;
for(int i=1;i<=n;i++)
{
cin>>sum[i];
sum[i]+=sum[i-1];
mp[i]=sum[i];
}
sort(mp+1,mp+n+1);
m=unique(mp+1,mp+n+1)-mp-1;
for(int i=1;i<=n;i++)
{
int pos=lower_bound(mp+1,mp+m+1,sum[i])-mp;
sum[i]=pos;
}
for(int i=l;i<=r;i++)
add(sum[i],1);
long long ans=0;
for(int i=1;i<=n;i++)
{
int pos=lower_bound(mp+1,mp+m+1,s+mp[sum[i-1]])-mp-1;
ans+=get(m)-get(pos);
add(sum[l++],-1);
if(r<n) add(sum[++r],1);
if(l>n) break;
}
cout<<ans<<endl;
return 0;
}