当前位置:   article > 正文

牛客周赛 Round 28 F_牛客周赛 round 28 题解

牛客周赛 round 28 题解

F.小红统计区间(hard)

题目链接

Sum[r]-Sum[l]\geq k\ \Rightarrow \ Sum[r]-k\geq Sum[l]\ \Rightarrow \ ans++

Sum[i]\geq k\Rightarrow ans++

Sum[i]为前缀和

  • 枚举右端点看有多少个左端点满足条件,即在一个数轴上找x\leq Sum[i]-kx的个数。可以利用树状数组区间查询,查找1\rightarrow i-1中满足条件的前缀和。具体操作为先查找,再把自身在数轴上对应的数的个数加一。所以统计时没有统计Sum[i]\geq k自身对答案的影响。当前操作为第i位时,则数轴上只记录了1\rightarrow i-1的前缀和。
  • 由于前缀和过大,形成的数轴过长,采用离散化。将所有前缀和由小到大排序并去重,构成新数轴。
  • 由于Sum[l]-k在数轴上可能没有直接映射,所以通过二分找到满足条件的最大的前缀和,转为统计小于等于它的前缀和个数。找不到就不更新ans
  • ans最大会到1e10,会爆int
  1. import java.io.*;
  2. import java.util.Arrays;
  3. import java.util.HashMap;
  4. import java.util.Scanner;
  5. public class Main{
  6. static
  7. class BIT{
  8. int size;
  9. long[] tr;
  10. public BIT(int n) {
  11. size=n;
  12. tr=new long[n+1];
  13. }
  14. public int lowbit(int x) {
  15. return x&(-x);
  16. }
  17. public void update(int x) {
  18. for(int i=x;i<=size;i+=lowbit(i)) {
  19. tr[i]++;
  20. }
  21. }
  22. public long query(int x) {//区间组合最多1e10,int会爆
  23. long ans=0;
  24. for(int i=x;i>0;i-=lowbit(i)) {
  25. ans+=tr[i];
  26. }
  27. return ans;
  28. }
  29. }
  30. public static void main(String[] args) throws IOException{
  31. Scanner input=new Scanner(System.in);
  32. int n=input.nextInt();
  33. long k=input.nextLong();
  34. long ans=0;
  35. long[] Sum=new long[n];//用于离散化的前缀和
  36. long[] pre=new long[n];//保留原本的前缀和
  37. Sum[0]=input.nextLong();
  38. if(Sum[0]>=k)ans++;
  39. pre[0]=Sum[0];
  40. for(int i=1;i<n;++i) {
  41. Sum[i]=input.nextLong();
  42. Sum[i]+=Sum[i-1];
  43. if(Sum[i]>=k)ans++;
  44. pre[i]=Sum[i];
  45. }
  46. Arrays.sort(Sum);
  47. HashMap<Long,Integer> hs=new HashMap<Long, Integer>();
  48. int cnt=0;
  49. long[] Qu=new long[n+1];//离散后数轴每位对应的前缀和
  50. for(int i=0;i<n;++i) {
  51. if(hs.get(Sum[i])==null) {
  52. cnt++;
  53. hs.put(Sum[i], cnt);
  54. Qu[cnt]=Sum[i];
  55. }
  56. }
  57. //排序后位置不同,可能在后面的前缀和被移到前面或在前面的前缀和被移到后面
  58. BIT Tr=new BIT(cnt);
  59. Tr.update(hs.get(pre[0]));
  60. for(int i=1;i<n;++i) {
  61. long y=pre[i]-k;
  62. int l=1,r=cnt,id=-1;//二分查找
  63. while(l<=r) {
  64. int mid=(l+r)>>1;
  65. if(Qu[mid]<=y) {
  66. id=mid;
  67. l=mid+1;
  68. }
  69. else r=mid-1;
  70. }
  71. if(id!=-1)ans+=Tr.query(hs.get(Qu[id]));
  72. Tr.update(hs.get(pre[i]));
  73. }
  74. System.out.println(ans);
  75. }
  76. }

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

闽ICP备14008679号