线段树总结

今天学习线段树,有一些感悟。

第一,要想清楚pushdown和pushup的用处:

一个是将u的信息传递给子节点,一个是将子节点的信息传递给父亲节点。

第二,建树的判定:

当left和right相等时,赋值成输入的a[u],然后return,完成部分的建树。

第三,更新时要分3种情况:

其一是所要更新的区间全部在s[u].l到mid时,直接在L(u)继续向下找,这里要注意,所找的区间还是left到right,跟mid无关。

其二是所要更新的区间全部在mid到s[u].r时,在R(u)继续向下找,这里也要注意,所找的区间还是left到right。

其三是所要更新的区间在两边都有交集时,要分两边找,这里要注意:所找的区间就是left到mid和mid+1到right了。千万不能写错!(调了很久才发现。⊙﹏⊙b汗)

第四,结构体:

结构体内定义left,right表示s[u]区间的两端,其他变量由题意定义。(例如sum,height,add,price等)结构体外的数组一般定成4*MAXN那么大就可以了。

第五:格式:

一定要看清题目的输入格式和输出格式!有些题输入是多组数据,还有输出时一般情况要换行。

下面是线段树的一些基本框架:

1.建树:

void Build (int u,int left,int right)//u表当前结点
 { //left right 表左区间范围[left,right]
    node[u].l = left,node[u].r = right;
    …..                              //结点信息的初始化
    if (node[u].l == node[u].r)     //到叶结点 return
    {
        ……                         //某些赋值
        return ;
    }
    int mid = (node[u].l + node[u].r)>>1;
    Build (L(u),left,mid);
    Build (R(u),mid+1,right);
}
 2.更新:
void Update(int u,int left,int right,data val)
{
    if (left<=node[u].l&&node[u].r <= right){
        ……..               //进行某些更改操作
        return ;
    }
     Pushdown(u);          // 成段更新时,这里一般都有个延时更新
    int mid = (node[u].l + node[u].r)>>1;   //然后就是往左 往右 或左右找区间 几乎所有的
    if (right <= mid) Update(L(u),left,right,val);             //线段树都这样
    else if (left > mid) Update(R(u),left,right,val);
    else {
        Update(L(u),left,mid,val);
        Update(R(u),mid+1,right,val);
    }
    Pushup(u);        //这里也一般有个向上更新
}
 3.查询:
int Query(int u,int left,int right)
{
    if (left <= node[u].l&&node[u].r <= right)
        return node[u].sum;
    Pushdown(u);    //同update操作 视情况可有可无
    int mid = (node[u].l + node[u].r)>>1;
    if (right <= mid) return Query(L(u),left,right);
    else if (left > mid) return Query(R(u),left,right);
    else return (Query(L(u),left,mid) + Query(R(u),mid+1,right));
    Pushup(u);       //
}
 4.向上回溯:
void Pushup(int u)
{
    node[u].sum = node[L(u)].sum + node[R(u)].sum;
    …….
    …….
    return ;
}
 5.延时更新(向下更改):
void Pushdown (int u)   //延迟覆盖操作
{
    if (node[u].state == -1) {
      更新父结点,左右子结点信息
    }
    else if (node[u].state == 1){
            更新父结点,左右子结点信息
    }
    else {
………
}
}
 
 

 

posted @ 2016-07-13 17:20  deadshotz  阅读(155)  评论(0编辑  收藏  举报