当前位置:   article > 正文

洛谷1714线段树加前缀和_在前缀和上的线段树

在前缀和上的线段树

题目传送门:https://www.luogu.org/problemnew/show/P1714

题意很简单,在一段长度为n的序列里找出长度小于k的一段连续序列的最大值,是线段树无疑了。但是假如写一个求区间和的线段树你的复杂度大概为o(n^2logn),你要研究(1,k),(1,k-1)……(1,1,)中的最大值然后将以上操作重复n遍(严格来说没有n遍因为从n出发后只有(n,n),但无伤大雅,对于N≤500000肯定是gg的),那么我们想到没有学线段树的时候第一次听到求区间和的时候我第一个想到的是前缀和(因为当时没有引入维护),那么这个题也可以利用前缀和。将a数组利用前缀和维护之后,我要求的变成了(a[i]-a[i-1]),(a[i]-a[i-2])……(a[i]-a[i-k+1])时的最大值,那么我们用线段树维护a[i-1]到a[i-k+1]时的最小值即可,时间复杂度(nlogn),附上代码:

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. struct seg{
  4. int val;
  5. }seg[2000010];
  6. int n,k;
  7. int a[1000001]={0};
  8. int max=-10000000;
  9. int min(int x,int y)
  10. {
  11. if(x>y)
  12. return y;
  13. else return x;
  14. }
  15. int quire(int root,int nstart,int nend,int qstart,int qend)
  16. {
  17. int mid;
  18. if(nstart>qend||qstart>nend)
  19. return 100000000;
  20. if(nstart>=qstart&&nend<=qend)
  21. return seg[root].val;
  22. mid=(nstart+nend)/2;
  23. return min(quire(root*2,nstart,mid,qstart,qend),quire(root*2+1,mid+1,nend,qstart,qend));
  24. }
  25. int build(int root,int istart,int iend)
  26. {
  27. int mid;
  28. if(istart==iend)
  29. {
  30. seg[root].val=a[istart];
  31. return 0;
  32. }
  33. mid=(istart+iend)/2;
  34. build(root*2,istart,mid);
  35. build(root*2+1,mid+1,iend);
  36. seg[root].val=min(seg[root*2].val,seg[root*2+1].val);
  37. return 0;
  38. }
  39. int main()
  40. {
  41. int i;
  42. scanf("%d%d",&n,&k);
  43. for(i=1;i<=n;i++)
  44. {
  45. scanf("%d",&a[i]);
  46. a[i]+=a[i-1];
  47. }
  48. build(1,1,n);
  49. for(i=1;i<=n;i++)
  50. {
  51. if(i-k>=1)
  52. {
  53. if(a[i]-quire(1,1,n,i-k,i)>max)
  54. max=a[i]-quire(1,1,n,i-k,i);
  55. }
  56. else if(a[i]-quire(1,1,n,1,i)>max)
  57. max=a[i]-quire(1,1,n,1,i);
  58. }
  59. printf("%d",max);
  60. return 0;
  61. }

 

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

闽ICP备14008679号