不会cdq的看这里:cdq分治:从分治到套娃
转化为求 j<i,L<=sum[i]-sum[j-1]<=R的对数的问题,其中sum为前缀和
经典的三维偏序,当然也可以分治后排序再用队列来维护。
你也可以试试直接用数据结构来做(话说cdq不就是把数据结构转成了归并排序来做的嘛)
#include<algorithm>
#include<iostream>
#include<cstdio>
#define LL long long
using namespace std;
int n;
LL L,R,ans;
const int N=100005;
LL sum[N],tmp[N];
void cdq(int l,int r)
{
if(l==r)return;
int mid=(l+r)>>1;
cdq(l,mid);cdq(mid+1,r);
int head=l,tail=l-1;
for(int i=mid+1;i<=r;++i)
{
while(tail+1<=mid&&sum[i]-sum[tail+1]>=L)++tail;
while(head<=mid&&sum[i]-sum[head]>R)++head;
ans+=tail-head+1;
}
// 下面的过程相当于sort(sum+l,sum+r+1); 但用时不一样
int now=l,i=l,j=mid+1;
while(i<=mid&&j<=r)
if(sum[i]<=sum[j])tmp[now]=sum[i],++now,++i;
else tmp[now]=sum[j],++now,++j;
for(;i<=mid;++i)tmp[now]=sum[i],++now;
for(;j<=r;++j)tmp[now]=sum[j],++now;
for(int i=l;i<=r;++i)sum[i]=tmp[i];
}
int main()
{
cin>>n>>L>>R;
for(int i=1,x;i<=n;++i)scanf("%d",&x),sum[i]=sum[i-1]+x;
cdq(0,n);cout<<ans;
return 0;
}