赞
踩
题面传送门
题目要求有多少个
i
,
j
i,j
i,j使的
l
≤
∑
k
=
i
j
a
i
≤
r
l\leq \sum\limits_{k=i}^{j}{a_i}\leq r
l≤k=i∑jai≤r
用前缀和搞一下,变成
l
≤
q
j
−
q
i
−
1
≤
r
l\leq q_j-q_{i-1}\leq r
l≤qj−qi−1≤r
再变换一下,变成
q
j
−
r
≤
q
i
−
1
≤
q
j
−
l
q_j-r\leq q_{i-1}\leq q_j-l
qj−r≤qi−1≤qj−l
然后动态开点线段树或者平衡树一搞就好了。
代码实现:
#include<cstdio> using namespace std; long long n,m,k,x,y,z,a[100039],tot=1; long long q[100039],ans,l,r; struct tree{int l,r,sum;}f[5000039]; inline void get(long long x,long long l,long long r,int now){ if(l==r){f[now].sum++;return;} long long m=(l+r)>>1; if(x<=m){ if(!f[now].l) f[now].l=++tot; get(x,l,m,f[now].l); } else{ if(!f[now].r) f[now].r=++tot; get(x,m+1,r,f[now].r); } f[now].sum=f[f[now].l].sum+f[f[now].r].sum; } inline int find(long long x,long long y,long long l,long long r,int now){ if(x<=l&&r<=y) return f[now].sum; long long m=(l+r)>>1; int fs=0; if(x<=m&&f[now].l) fs+=find(x,y,l,m,f[now].l); if(y>m&&f[now].r) fs+=find(x,y,m+1,r,f[now].r); return fs; } int main(){ //freopen("1.in","r",stdin); register int i; scanf("%lld%lld%lld",&n,&l,&r); for(i=1;i<=n;i++) scanf("%lld",&a[i]),q[i]=q[i-1]+a[i]; get(0,(long long)-1e10-1e9,(long long)1e10,1); for(i=1;i<=n;i++){ ans+=find(q[i]-r,q[i]-l,(long long)-1e10-1e9,(long long)1e10,1); get(q[i],(long long)-1e10-1e9,(long long)1e10,1); } printf("%lld\n",ans); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。