当前位置:   article > 正文

【树状数组】【BJOI2016】回转寿司_回转寿司 树状数组

回转寿司 树状数组


题目告诉我们要求连续区间价值大于等于l,小于等于r的数量,我们考虑使用前缀和维护

以sum[i]为结尾的符合条件的区间数量即sum[i]-r至sum[i]-l这段区间中所包含的前面的前缀和的数量

我们考虑使用数组离散化维护

不把sum[i]-l和sum[i]-r加入也可以,代码中为避免麻烦加入了

  1. #include<iostream>
  2. #include<iomanip>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<algorithm>
  7. #include<queue>
  8. #include<map>
  9. using namespace std;
  10. char c;
  11. int read()
  12. {
  13. int res=0,bj=1;
  14. while(c<'0'||c>'9'){if(c=='-') bj=-1; c=getchar();};
  15. while(c>='0'&&c<='9'){res=(res<<3)+(res<<1)+(c^48); c=getchar();};
  16. return res*bj;
  17. }
  18. int n,l,r,N,tree[300005];
  19. long long sum[100005],a[300005],ans;
  20. int find(int x)
  21. {
  22. int l=1,r=N;
  23. while(l<r)
  24. {
  25. int mid=(l+r+1)>>1;
  26. if(a[mid]>x) r=mid-1;
  27. else l=mid;
  28. }
  29. return l;
  30. }
  31. void add(int x,int v)
  32. {
  33. while(x<=N) tree[x]+=v,x+=(x&-x);
  34. }
  35. int ask(int x)
  36. {
  37. int ans=0;
  38. while(x) ans+=tree[x],x-=(x&-x);
  39. return ans;
  40. }
  41. int main()
  42. {
  43. scanf("%d%d%d",&n,&l,&r);
  44. a[++N]=0;
  45. for(int i=1;i<=n;i++) sum[i]=sum[i-1]+read(),a[++N]=sum[i],a[++N]=sum[i]-l,a[++N]=sum[i]-r-1;
  46. sort(a+1,a+N+1);
  47. N=unique(a+1,a+N+1)-a-1;
  48. for(int i=0;i<=n;i++)
  49. {
  50. int ls=lower_bound(a+1,a+N+1,sum[i]-r-1)-a;
  51. int rs=lower_bound(a+1,a+N+1,sum[i]-l)-a;
  52. ans+=ask(rs)-ask(ls);
  53. int x=lower_bound(a+1,a+N+1,sum[i])-a;
  54. add(x,1);
  55. }
  56. printf("%lld",ans);
  57. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/622365
推荐阅读
相关标签
  

闽ICP备14008679号