线段树板子

忘是亡心i 2022-03-10 03:30 345阅读 0赞

直接上板子:希望以后复习用到!

  1. #include<cstdio>
  2. using namespace std;
  3. int n,p,a,b,m,x,y,ans;
  4. struct node
  5. {
  6. int l,r,w,f;
  7. }tree[400001];
  8. inline void build(int k,int ll,int rr)//建树
  9. {
  10. tree[k].l=ll,tree[k].r=rr;
  11. if(tree[k].l==tree[k].r)
  12. {
  13. scanf("%d",&tree[k].w);
  14. return;
  15. }
  16. int m=(ll+rr)/2;
  17. build(k*2,ll,m);
  18. build(k*2+1,m+1,rr);
  19. tree[k].w=tree[k*2].w+tree[k*2+1].w;
  20. }
  21. inline void down(int k)//标记下传
  22. {
  23. tree[k*2].f+=tree[k].f;
  24. tree[k*2+1].f+=tree[k].f;
  25. tree[k*2].w+=tree[k].f*(tree[k*2].r-tree[k*2].l+1);
  26. tree[k*2+1].w+=tree[k].f*(tree[k*2+1].r-tree[k*2+1].l+1);
  27. tree[k].f=0;
  28. }
  29. inline void ask_point(int k)//单点查询
  30. {
  31. if(tree[k].l==tree[k].r)
  32. {
  33. ans=tree[k].w;
  34. return ;
  35. }
  36. if(tree[k].f) down(k);
  37. int m=(tree[k].l+tree[k].r)/2;
  38. if(x<=m) ask_point(k*2);
  39. else ask_point(k*2+1);
  40. }
  41. inline void change_point(int k)//单点修改
  42. {
  43. if(tree[k].l==tree[k].r)
  44. {
  45. tree[k].w+=y;
  46. return;
  47. }
  48. if(tree[k].f) down(k);
  49. int m=(tree[k].l+tree[k].r)/2;
  50. if(x<=m) change_point(k*2);
  51. else change_point(k*2+1);
  52. tree[k].w=tree[k*2].w+tree[k*2+1].w;
  53. }
  54. inline void ask_interval(int k)//区间查询
  55. {
  56. if(tree[k].l>=a&&tree[k].r<=b)
  57. {
  58. ans+=tree[k].w;
  59. return;
  60. }
  61. if(tree[k].f) down(k);
  62. int m=(tree[k].l+tree[k].r)/2;
  63. if(a<=m) ask_interval(k*2);
  64. if(b>m) ask_interval(k*2+1);
  65. }
  66. inline void change_interval(int k)//区间修改
  67. {
  68. if(tree[k].l>=a&&tree[k].r<=b)
  69. {
  70. tree[k].w+=(tree[k].r-tree[k].l+1)*y;
  71. tree[k].f+=y;
  72. return ;
  73. }
  74. if(tree[k].f) down(k);
  75. int m=(tree[k].l+tree[k].r)/2;
  76. if(a<=m) change_interval(k*2);
  77. if(b>m) change_interval(k*2+1);
  78. tree[k].w=tree[k*2].w+tree[k*2+1].w;
  79. }
  80. int main()
  81. {
  82. scanf("%d",&n);//n个节点
  83. build(1,1,n);//建树
  84. scanf("%d",&m);//m种操作
  85. for(int i=1;i<=m;i++)
  86. {
  87. scanf("%d",&p);
  88. ans=0;
  89. if(p==1)
  90. {
  91. scanf("%d",&x);
  92. ask_point(1);//单点查询,输出第x个数
  93. printf("%d",ans);
  94. }
  95. else if(p==2)
  96. {
  97. scanf("%d%d",&x,&y);
  98. change_point(1);//单点修改
  99. }
  100. else if(p==3)
  101. {
  102. scanf("%d%d",&a,&b);//区间查询
  103. ask_interval(1);
  104. printf("%d\n",ans);
  105. }
  106. else
  107. {
  108. scanf("%d%d%d",&a,&b,&y);//区间修改
  109. change_interval(1);
  110. }
  111. }
  112. }

发表评论

表情:
评论列表 (有 0 条评论,345人围观)

还没有评论,来说两句吧...

相关阅读

    相关 线段

    线段树入门: 转载博客:[点击打开链接][Link 1] 前几天开始接触线段树,其一些基本的操作还是很容易理解的,但是区间更新我着实理解了好一会(因该是本人太菜),今天有时

    相关 线段

    一 概述 线段树,类似区间树,它在各个节点保存一条线段(数组中的一段子数组),主要用于高效解决连续区间的动态查询问题,由于二叉结构的特性,它基本能保持每个操作的复杂度为O(l