HDU 1698 线段树区间更新以及lazy思想

来源:互联网 发布:nginx配置静态页面 编辑:程序博客网 时间:2024/05/17 03:40

线段树是一种二叉搜索数,每一个节点都对应一定的区间,能够快速的对区间进行更新,时间复杂度比较小;
常运用于线段树的一个算法是lazy思想,lazy思想是说若更新的区间已经完全包含区间s,将s区间标记,暂不向下更新,若下一次的更新或

询问需要用的已经标记过的区间的子区间,再将标记过得区间进行向下更新,并且取消对区间s的标记,增加对区间两个左右子树的标记。若

一直未询问到,则不向下更新。通过这种方式可以达到节约时间的目的。


举例说明: 进行区间更新,并进行区间求和;

声明节点:
struct point
{
    int l,r;
    int x,add;//x为当前区间的总价值,add对应的是当前区间的值
    bool is_updata;// 判断是否更新;
};
node tree[4*maxn];

//向上更新:
void updata_up(int k)
{
    tree[k].x=tree[k<<1].x+tree[k<<1|1].x;
}
//向下更新
void updata_down(int k)
{
    if(tree[k].is_updata)
    {
        tree[k<<1|1].x=(tree[k<<1|1].r-tree[k<<1|1].l+1)*tree[k].add;
        tree[k<<1].x=(tree[k<<1].r-tree[k<<1].l+1)*tree[k].add;
        tree[k<<1|1].add=tree[k<<1].add=tree[k].add;
        tree[k<<1|1].is_updata=tree[k<<1].is_updata=true;
        tree[k].is_updata=false;
    }
}
//建立二叉树
void build(int l,int r,int k)
{
    tree[k].l=l,tree[k].r=r;
    tree[k].is_updata=false,tree[k].x=0;
    tree[k].add=0;
    if(l==r)
    {
        tree[k].x=1;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,k<<1);//头节点为1;
    build(mid+1,r,k<<1|1);
    updata_up(k);
}

//进行区间更新
void updata(int l,int r,int x,int k)
{
    if(tree[k].l>=l&&tree[k].r<=r)
    {
        tree[k].x=(tree[k].r-tree[k].l+1)*x;
        tree[k].add=x;
        if(r!=l) tree[k].is_updata=true;// 将区间标记,暂不向下更新
        return;
    }
    updata_down(k);//判断节点k是否被标记过,若被标记过,则此时需要向下更新
    if(tree[k<<1].r>=l) updata(l,r,x,k<<1);
    if(tree[k<<1|1].l<=r) updata(l,r,x,k<<1|1);
    updata_up(k);
}

最后直接输出tree[k].x即为所求;

0 0