zoukankan      html  css  js  c++  java
  • 线段树模板

     1 #define ls l,m,rt<<1
     2 #define rs m+1,r,rt<<1|1
     3 using namespace std;
     4 const int maxn=100005;
     5 int sum[maxn<<2],add[maxn<<2];//sum求和,add懒惰标记
     6 int a[maxn],n;//存原数组数据下标[1,n]
     7 //更新节点信息,这里是求和
     8 void pushup(int rt)
     9 {
    10     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    11 }
    12 //建树
    13 void build(int l,int r,int rt)//rt表示当前节点编号
    14 {
    15     if(l==r)
    16     {
    17        sum[rt]=a[l];
    18        return;
    19     }
    20     int m=(l+r)>>1;
    21     build(l,m,rt<<1);
    22     build(m+1,r,rt<<1|1);
    23     pushup(rt);
    24 }
    25 
    26 //点修改a[L]+=c;
    27 void update(int L,int c,int l,int r,int rt)
    28 {//l,r当前节点区间,rt当前节点编号,L需要修改的节点,c修改的值
    29     if(l==r)
    30     {
    31         sum[rt]+=c;
    32         return;
    33     }
    34     int m=(l+r)>>1;
    35     //根据条件判断调用左子树还是右子树
    36     if(L<=m)
    37         update(L,c,l,m,rt<<1);
    38     else
    39         update(L,c,m+1,r,rt<<1|1);
    40     pushup(rt);//子节点更新,所以本节点也需要更新
    41 }
    42 
    43 //区间修改a[r,t]+=c
    44 void update_(int L,int R,int c,int l,int r,int rt)
    45 {//L,R表示操作区间,l,r表示当前节点区间,rt表示当前节点编号
    46     if(L<=l&&r<=R)//遍历的区间在操作区间内
    47     {
    48         sum[rt]+=c*(r-l+1);
    49         add[rt]+=c;
    50         return;
    51     }
    52     int m=(l+r)>>1;
    53     pushdown(rt,m-l+1,r-m);
    54     if(L<=m)
    55         update_(L,R,c,l,m,rt<<1);
    56     if(R>m)
    57         update_(L,R,c,m+1,r,rt<<1|1);
    58     pushup(rt);
    59 }
    60 //区间查询 a[l,r]的和
    61 //下推标记函数
    62 void pushdown(int rt,int ln,int rn)
    63 {//ln,rn为左子树,右子树的数量
    64     if(add[rt])//下推标记
    65     {
    66         add[rt<<1]+=add[rt];
    67         add[rt<<1|1]+=add[rt];
    68         sum[rt<<1]+=add[rt]*ln;
    69         sum[rt<<1|1]+=add[rt]*rn;
    70         add[rt]=0;//清除本节点标记
    71     }
    72 }
    73 int query(int L,int R,int l,int r,int rt)
    74 {
    75     if(L<=l&&r<=R)
    76     {
    77         return sum[rt];
    78     }
    79     int m=(l+r)>>1;
    80     pushdown(rt,m-l+1,r-m);
    81     int ans=0;
    82     if(L<=m)
    83         ans+=query(L,R,l,m,rt<<1);
    84     if(R>m)
    85         ans+=query(L,R,m+1,r,rt<<1|1);
    86     return ans;
    87 }

    理解参考:

    https://blog.csdn.net/iwts_24/article/details/81484561

  • 相关阅读:
    学习方法
    编译原理词法分析程序
    06_05_词法分析
    顺序队列的基本操作
    使用默认参数的构造函数
    基于顺序栈的进制转换
    C语言之大数相加
    输入一个年输出其天干地支纪年法的表达式
    队列的链式存储及其基本运算
    队列的顺序存储及其基本操作
  • 原文地址:https://www.cnblogs.com/zuiaimiusi/p/10744656.html
Copyright © 2011-2022 走看看