线段树知识点

来源:互联网 发布:你凭什么看不起程序员 编辑:程序博客网 时间:2024/06/01 07:49

线段树解决的主要问题:1 单点更新,区间查询 2 区间更新,单点查询 3 区间更新,区间查询


线段树的本质是一棵二叉树,线段树的每一个节点记录的是一段区间的信息。
e.g. 对于长度为5的数组a[1]~a[5]
       [1,5]                                          
     
   [1,3]     [4,5]                                              对于任一非叶子节点,若该区间为[L,R],则
    [1,2] [3,3] [4,4] [5,5]                                 左儿子为[L,(L+R)/2]
                                                                  右儿子为[(L+R)/2+1,R]




  对于任一节点a[k],
它的左儿子为a[2*k]
它的右儿子为a[2*k




         线段树空间应开为原数组长度的4倍

             


   课件中的方法:         

lsonrson分辨表示结点的左儿子和右儿子,由于每次传参数的时候都固定是这几个变量,所以可以用预定于比较方便的表示

PushUP(int rt)是把当前结点的信息更新到父结点

PushDown(int rt)是把当前结点的信息更新给儿子结点

建树

void PushUP(int rt) {

MAX[rt] = MAX[rt<<1] + MAX[rt<<1|1];

}//具体问题具体分析

void build(int l,int r,int rt) {

if (l == r) {

scanf("%d",&MAX[rt]);

return ;

}

int m = (l + r) >> 1;

build(lson);

build(rson);

PushUP(rt);

}// build(1,n,1)

更新

void update(int p,int sc,int l,int r,int rt) {更新的输的位置 输入跟新的树

if (l == r) {

MAX[rt] = sc;//具体问题具体分析

return ;

}

int m = (l + r) >> 1;

if (p <= m) update(p , sc , lson);

else update(p , sc , rson);

PushUP(rt);

}

查询

int query(int L,int R,int l,int r,int rt) {

if (L <= l && r <= R) {

return MAX[rt];

}

int m = (l + r) >> 1;

int ret = 0;

if (L <= m) ret =max(ret , query(L , R , lson));具体问题具体分析

if (R > m) ret =max(ret , query(L , R , rson));

return ret;

}