线段树是非常有效的数据结构,可以快速的维护单点修改,区域修改,查询最大值,最小值等功能。

同时,它也很重要。如果有一天比赛,你卡在了一道线段树模板题目上,这就真的尴尬了。不过,随着时代的进步,题目也越来越变态,线段树更多时候则是你算法时间复杂度的优化。

这是单点查询的代码。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. using namespace std;
  5.  
  6. int n;
  7. int a[];
  8.  
  9. struct node
  10. {
  11. int l;
  12. int r;
  13. int sum;
  14. } t[];
  15.  
  16. void build (int i,int l,int r)
  17. {
  18. t[i].l=l;
  19. t[i].r=r;
  20. int mid=l+r>>;
  21. if (l==r)
  22. {
  23. t[i].sum=a[l];return ;
  24. }
  25.  
  26. build(i<<,l,mid);
  27. build((i<<)+,mid+,r);
  28.  
  29. t[i].sum=t[i<<].sum+t[(i<<)+].sum;
  30.  
  31. return ;
  32. }
  33.  
  34. void update(int i,int p,int k)
  35. {
  36. if (t[i].l==t[i].r)
  37. {
  38. t[i].sum=k;
  39. return;
  40. }
  41.  
  42. int mid=t[i].l+t[i].r>>;
  43. if (p<=mid) update(i<<,p,k);
  44. if (p>mid) update((i<<)+,p,k);
  45. t[i].sum=t[i<<].sum+t[(i<<)+].sum;
  46.  
  47. return ;
  48. }
  49.  
  50. int getsum(int i,int l,int r)
  51. {
  52. int mid=(t[i].l+t[i].r)>>;
  53. if (l<=t[i].l&&t[i].r<=r) return t[i].sum;
  54. if (r<=mid) return getsum(i<<,l,r);
  55. if (l>mid) return getsum((i<<)+,l,r);
  56.  
  57. return getsum(i<<,l,r)+getsum((i<<)+,l,r);
  58. }
  59.  
  60. int main()
  61. {
  62. int m;
  63. scanf("%d%d",&n,&m);
  64. for (int i=;i<=m;i++)
  65. {
  66. scanf("%d",&a[i]);
  67. }
  68. build(,,n);
  69. while (m--)
  70. {
  71. int x,y,z;
  72. scanf("%d%d%d",&x,&y,&z);
  73. if (x==)
  74. {
  75. update(,y,z);
  76. }
  77. else printf("%d\n",getsum(,y,z));
  78. }
  79.  
  80. return ;
  81. }

下面是区间修改的代码。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <algorithm>
  4. #include <vector>
  5. #include <cmath>
  6. #include <set>
  7. using namespace std;
  8.  
  9. struct node
  10. {
  11. int l,r,s,d;
  12. } t[];
  13. int n,m;
  14. int a[];
  15.  
  16. void pushup(int x)
  17. {
  18. t[x].s=t[x<<].s+t[(x<<)+].s;
  19. return;
  20. }
  21.  
  22. void pushdown(int x)
  23. {
  24. int mid=(t[x].l+t[x].r)>>;
  25. int d=t[x].d;
  26. t[x<<].d+=d;t[(x<<)+].d+=d;
  27. t[x<<].s+=(mid-t[x].l+)*d;
  28. t[(x<<)+].s+=(t[x].r-mid)*d;
  29. return;
  30. }
  31.  
  32. void build(int i,int l,int r)
  33. {
  34. t[i].l=l;
  35. t[i].r=r;
  36. t[i].d=;
  37. if (l==r)
  38. {
  39. t[i].s=a[l];
  40. return ;
  41. }
  42.  
  43. int mid=l+r>>;
  44.  
  45. build(i<<,l,mid);
  46. build((i<<)+,mid+,r);
  47.  
  48. pushup(i);
  49. return;
  50. }
  51.  
  52. int getsum(int i,int l,int r)
  53. {
  54. int mid=t[i].l+t[i].r>>;
  55. if (l<=t[i].l&&t[i].r<=r)
  56. {
  57. return t[i].s;
  58. }
  59. int d=t[i].d;
  60. if (!d) pushdown(i);
  61. int ret=;
  62. if (mid>=l) ret+=getsum(i<<,l,r);
  63. if (mid<r) ret+=getsum((i<<)+,l,r);
  64.  
  65. return ret;
  66. }
  67.  
  68. void update(int i,int l,int r,int del)
  69. {
  70. if (t[i].l==t[i].r)
  71. {
  72. t[i].d+=del;
  73. t[i].s+=(t[i].l-t[i].r+)*del;
  74. return ;
  75. }
  76.  
  77. int mid=t[i].l+t[i].r>>;
  78. if (!t[i].d) pushdown(i);
  79. if (mid>=l) update(i<<,l,r,del);
  80. if (mid<r) update((i<<)+,l,r,del);
  81. pushup(i);
  82. }
  83.  
  84. int main()
  85. {
  86. scanf("%d%d",&n,&m);
  87. for (int i=;i<=n;i++)
  88. {
  89. scanf("%d",&a[i]);
  90. }
  91. build (,,n);
  92.  
  93. for (int i=;i<=m;i++)
  94. {
  95. int x,y,z,d;
  96. scanf("%d",&x);
  97. if (x==)
  98. {
  99. scanf("%d%d%d",&y,&z,&d);
  100. update(,y,z,d);
  101. }
  102. if (x==)
  103. {
  104. scanf("%d%d",&y,&z);
  105. printf("%d\n",getsum(,y,z));
  106. }
  107. }
  108.  
  109. return ;
  110. }

线段树:Segment Tree(单点修改/区间修改模板) C++的更多相关文章

  1. 『线段树 Segment Tree』

    更新了基础部分 更新了\(lazytag\)标记的讲解 线段树 Segment Tree 今天来讲一下经典的线段树. 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间 ...

  2. 线段树(Segment Tree)(转)

    原文链接:线段树(Segment Tree) 1.概述 线段树,也叫区间树,是一个完全二叉树,它在各个节点保存一条线段(即“子数组”),因而常用于解决数列维护问题,基本能保证每个操作的复杂度为O(lg ...

  3. BZOJ4999:This Problem Is Too Simple!(DFS序&树上差分&线段树动态开点:区间修改单点查询)

    Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x&l ...

  4. BZOJ.4695.最假女选手(线段树 Segment tree Beats!)

    题目链接 区间取\(\max,\ \min\)并维护区间和是普通线段树无法处理的. 对于操作二,维护区间最小值\(mn\).最小值个数\(t\).严格次小值\(se\). 当\(mn\geq x\)时 ...

  5. 【数据结构系列】线段树(Segment Tree)

    一.线段树的定义 线段树,又名区间树,是一种二叉搜索树. 那么问题来了,啥是二叉搜索树呢? 对于一棵二叉树,若满足: ①它的左子树不空,则左子树上所有结点的值均小于它的根结点的值 ②若它的右子树不空, ...

  6. 浅谈线段树 Segment Tree

    众所周知,线段树是algo中很重要的一项! 一.简介 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在 ...

  7. 线段树(segment tree)

    线段树在一些acm题目中经常见到,这种数据结构主要应用在计算几何和地理信息系统中.下图就为一个线段树: (PS:可能你见过线段树的不同表示方式,但是都大同小异,根据自己的需要来建就行.) 1.线段树基 ...

  8. poj 2763 Housewife Wind(树链剖分+单点查询+区间修改)

    题目链接:http://poj.org/problem?id=2763 题意:给一个数,边之间有权值,然后两种操作,第一种:求任意两点的权值和,第二,修改树上两点的权值. 题解:简单的树链剖分. #i ...

  9. 线段树 Interval Tree

    一.线段树 线段树既是线段也是树,并且是一棵二叉树,每个结点是一条线段,每条线段的左右儿子线段分别是该线段的左半和右半区间,递归定义之后就是一棵线段树. 例题:给定N条线段,{[2, 5], [4, ...

  10. Libre OJ 130、131、132 (树状数组 单点修改、区间查询 -> 区间修改,单点查询 -> 区间修改,区间查询)

    这三题均可以用树状数组.分块或线段树来做 #130. 树状数组 1 :单点修改,区间查询 题目链接:https://loj.ac/problem/130 题目描述 这是一道模板题. 给定数列 a[1] ...

随机推荐

  1. (摘)Zebra打印机异常处理

    一.一般条码打印设备按图指示方向,虚线为碳带安装路径,实线为标签路径.回卷后废碳带不易剥落,则在装入前用废标签的光滑底纸卷在回卷轴上,然后再上碳带.安装标签时,根据不同标签宽度调整限纸器.压头弹簧均匀 ...

  2. cursor: pin S

    declare v_sql varchar2(200); begin loop v_sql :='select seq1.nextval from dual'; execute immediate v ...

  3. Eclipse设置合适的字体

    一直使用Eclipse开发,最近感觉Comic Sans MS不错,但我的eclipse的默认字体里没有. 如果系统里有这个字体的话,那可以很简单的将这个字体添加到Eclipse中: Windows ...

  4. Java---设计模块(工厂方法)

    ★ 场景和问题 Java程序开发讲究面向接口编程,隐藏具体的实现类,可是如何得到接口呢? 工厂类的命名规范:***Factory 单例工厂方法的命名规范:getInstance() 工厂的本质是&qu ...

  5. cocos2d-x 几何绘制: DrawingPrimitives 和 CCDrawNode

    在看书的时候只提到了DrawingPrimitives,然后我去搜索这个类,结果没搜到.心想难道是类名改了,那我搜方法名吧,搜了下DrawLine,果然被我搜到了.结果发现原来这些各方法都是全局函数, ...

  6. 关于本学期西南交通大学ACM-ICPC校集训队 训练计划(Beta 1.0)

    在第十周新秀杯之后,从第十一周起的训练计划如下: 1.十一周的周一至周五进行ACM校集训队申请.申请方式从2014年11月17日0:00开始,发送申请者的姓名.学号.专业.电话.QQ以及大学(针对大一 ...

  7. springMVC学习(1)

    spring mvc的位置: springMVC只是spring的一个模块:   第一步:发起请求到前端控制器(DispatcherServlet) 第二步:DispatcherServlet请求Ha ...

  8. 浅谈C++中的那些内存泄露

    尽管学过C语言.可是C++里面的一些基础还是不太懂,还须要再掌握. 老范也開始要讲C++设计模式了,必须快点看了.不然就要白花窝滴钱了. 对于内存泄露,我的个人理解就是程序在执行过程中,自己开辟了空间 ...

  9. Codeforces Round #274 (Div. 2) E. Riding in a Lift(DP)

    Imagine that you are in a building that has exactly n floors. You can move between the floors in a l ...

  10. (第二章)Java并发机制的底层实现原理

    一.概述 Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,Java中所使用的并发机制依赖于JVM的实现和CPU的指令. ...