D - 集训难度 CSU - 2151

  这题就是有两种更新,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\n",query(1,l,r));
            }
    }
    return 0;
}

 

posted @ 2018-09-07 00:40  eason99  阅读(82)  评论(0编辑  收藏  举报