zoukankan      html  css  js  c++  java
  • D

      这题就是有两种更新,1.l~r区间每个数加v  2.l~r区间每个数都替换成v。2种更新就要对应2种lazy标记,lazy1是第一个更新方式的,lazy2是第二种更新方式的,当rt节点的区间先是进行了第二种更新方式,然后再进行第一种更新的话,就相当于是区间的每个数都变成了lazy2+lazy1,要是更新顺序反过来的话就不一样了,这个时候对区间里的每个数加上一个lazy1,然后又要把区间里的数都变成lazy2,那么第一种更新就失效了,即lazy1可以清除。

      

    #include<stdio.h>
    #include<iostream>
    using namespace std;
    const int maxn=1e5+10;
    #define ll long long
    #define rs 2*rt+1
    #define ls 2*rt
    struct node
    {
        int l,r;
        bool tag1,tag2;//tag1表示rt节点对应区间每个数要加lazy1,tag2表示rt节点对应区间每个数都变成lazy2
        ll lazy1,lazy2,sum;
    }tree[4*maxn];
    int n,m,v0;
    void build(int rt,int l,int r)
    {
        tree[rt].l=l;
        tree[rt].r=r;
        tree[rt].tag1=tree[rt].tag2=false;
        tree[rt].lazy1=tree[rt].lazy2=0;
        if(l==r)
        {
            tree[rt].sum=v0;
            return ;
        }
        int mid=(l+r)>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
        tree[rt].sum=tree[ls].sum+tree[rs].sum;
    }
    void pushdown(int rt)
    {
        if(tree[rt].tag2)//优先判断是否tag2存在,tag2存在的话说明rt节点对应的区间是先进行了第二种更新
        {
            tree[ls].tag1=tree[rs].tag1=false;//可能ls,rs有tag1,但是对ls,rs进行了第二种更新后,tag1就失效了
            tree[ls].lazy1=tree[rs].lazy1=0;
            tree[ls].tag2=tree[rs].tag2=true;
            tree[ls].lazy2=tree[rs].lazy2=tree[rt].lazy2;
            tree[ls].sum=(tree[ls].r-tree[ls].l+1)*tree[rt].lazy2;
            tree[rs].sum=(tree[rs].r-tree[rs].l+1)*tree[rt].lazy2;
            tree[rt].tag2=false;
            tree[rt].lazy2=0;
        }
        if(tree[rt].tag1)如果tag2和tag1都存在的话说明是先进行了第二种更新,后进行了第一种更新
        {
            tree[ls].tag1=tree[rs].tag1=true;
            tree[ls].lazy1+=tree[rt].lazy1;
            tree[rs].lazy1+=tree[rt].lazy1;
            tree[ls].sum+=(tree[ls].r-tree[ls].l+1)*tree[rt].lazy1;
            tree[rs].sum+=(tree[rs].r-tree[rs].l+1)*tree[rt].lazy1;
            tree[rt].tag1=false;
            tree[rt].lazy1=0;
        }
    
    }
    void update1(int rt,int l,int r,int v)//第一种更新
    {
        if(tree[rt].l>=l&&tree[rt].r<=r)
        {
            tree[rt].tag1=true;
            tree[rt].lazy1+=v;
            tree[rt].sum+=(tree[rt].r-tree[rt].l+1)*v;
            return ;
        }
        pushdown(rt);
        int mid=(tree[rt].r+tree[rt].l)>>1;
        if(mid+1<=l)
            update1(rs,l,r,v);
        else
            if(r<=mid)
                update1(ls,l,r,v);
            else
            {
                update1(ls,l,r,v);
                update1(rs,l,r,v);
            }
        tree[rt].sum=tree[ls].sum+tree[rs].sum;
    }
    void update2(int rt,int l,int r,int v)//第一种更新
    {
        if(tree[rt].l>=l&&tree[rt].r<=r)
        {
            tree[rt].tag1=false;//再对rt节点成段进行第二种更新时,需要把rt之前的第一次更新清除了
            tree[rt].lazy1=0;
            tree[rt].tag2=true;
            tree[rt].lazy2=v;
            tree[rt].sum=(tree[rt].r-tree[rt].l+1)*v;
            return ;
        }
        pushdown(rt);
        int mid=(tree[rt].r+tree[rt].l)>>1;
        if(mid+1<=l)
            update2(rs,l,r,v);
        else
            if(r<=mid)
                update2(ls,l,r,v);
            else
            {
                update2(ls,l,r,v);
                update2(rs,l,r,v);
            }
        tree[rt].sum=tree[ls].sum+tree[rs].sum;
    }
    ll query(int rt,int l,int r)
    {
        if(tree[rt].l>=l&&tree[rt].r<=r)
            return tree[rt].sum;
        pushdown(rt);
        int mid=(tree[rt].l+tree[rt].r)>>1;
        ll ans=0;
        if(mid>=r)
            ans=query(ls,l,r);
        else
            if(mid+1<=l)
                ans=query(rs,l,r);
            else
            {
                ans=query(ls,l,r);
                ans+=query(rs,l,r);
            }
        return ans;
    }
    int main()
    {
        scanf("%d %d %d",&n,&m,&v0);
        build(1,1,n);
        while(m--)
        {
            int flag;
            scanf("%d",&flag);
            if(flag==0)
            {
                int l,r,v;
                scanf("%d %d %d",&l,&r,&v);
                update1(1,l,r,v);
            }
            else
                if(flag==1)
                {
                    int l,r,v;
                    scanf("%d %d %d",&l,&r,&v);
                    update2(1,l,r,v);
                }
                else
                {
                    int l,r;
                    scanf("%d %d",&l,&r);
                    printf("%lld
    ",query(1,l,r));
                }
        }
        return 0;
    }
  • 相关阅读:
    浮点数越界或者无效1.#IND0
    [转]方差、协方差与相关系数
    『转』 函数、变量命名方法
    感知哈希算法——google用于图片搜索的算法
    C#传值调用与引用调用 解释
    HttpContext.Current.Request.ServerVariab
    怎么去用java经典递归算法?
    泛型的详细解释与示例
    个彻底解释 C#泛型的源代码
    VC++怎么实现Win2000下直接读写磁盘扇区
  • 原文地址:https://www.cnblogs.com/eason9906/p/11754885.html
Copyright © 2011-2022 走看看