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;
    }
  • 相关阅读:
    [Vim].vimrc
    [笔试面试][code_by_hand]压缩字符串
    [笔试面试][code_by_hand]输出第二个字符串在第一个字符串中的连接次序
    [笔试面试]串s1="ABCDACDAE" s2="DAE" 找出s1中,包含s2的最小子串,要求该子串含有s2中的所有字符,串内字符无顺序关系
    [笔试面试][code_by_hand]从二元树中找出和为某一值的所有路径
    DEV 皮肤的使用
    Dev GridControl使用小结
    [转载]DEV控件:gridControl常用属性设置
    C#网页 自动登录 提交POST信息 方法
    比较字符串NSString
  • 原文地址:https://www.cnblogs.com/eason9906/p/11754885.html
Copyright © 2011-2022 走看看