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;
}