hihoCoder#1080 (线段树)

时间:2022-12-08 12:00:50

题目大意:线段树的区间更改与查询,但是涉及到两种区间修改方式,一是给区间中的数全部加上一个数,二是将一个区间全部置为同一个数,然后询问整个区间和。

题目分析:处理好set操作和add操作的先后顺序就OK了。

代码如下:

# include<iostream>
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std; const int N=100001; int n,m;
int tr[N*4+5];
int lazy_set[N*4+5];
int lazy_add[N*4+5]; void pushDown(int rt,int l,int r)
{
int mid=l+(r-l)/2;
if(lazy_set[rt]!=0){
lazy_set[rt<<1]=lazy_set[rt<<1|1]=lazy_set[rt];
lazy_add[rt<<1]=lazy_add[rt<<1|1]=0;
tr[rt<<1]=lazy_set[rt]*(mid-l+1);
tr[rt<<1|1]=lazy_set[rt]*(r-mid);
lazy_set[rt]=0;
}
if(lazy_add[rt]!=0){
lazy_add[rt<<1]+=lazy_add[rt];
lazy_add[rt<<1|1]+=lazy_add[rt];
tr[rt<<1]+=lazy_add[rt]*(mid-l+1);
tr[rt<<1|1]+=lazy_add[rt]*(r-mid);
lazy_add[rt]=0;
}
} void makeTree(int rt,int l,int r)
{
if(l==r){
scanf("%d",&tr[rt]);
}else{
int mid=l+(r-l)/2;
makeTree(rt<<1,l,mid);
makeTree(rt<<1|1,mid+1,r);
tr[rt]=tr[rt<<1]+tr[rt<<1|1];
}
} void update(int rt,int l,int r,int L,int R,int x,int flag)
{
if(L<=l&&r<=R){
if(flag){
lazy_set[rt]=x;
lazy_add[rt]=0;
tr[rt]=x*(r-l+1);
}else{
lazy_add[rt]+=x;
tr[rt]+=x*(r-l+1);
}
}else{
pushDown(rt,l,r);
int mid=l+(r-l)/2;
if(L<=mid)
update(rt<<1,l,mid,L,R,x,flag);
if(R>mid)
update(rt<<1|1,mid+1,r,L,R,x,flag);
tr[rt]=tr[rt<<1]+tr[rt<<1|1];
}
} int main()
{
while(~scanf("%d%d",&n,&m))
{
memset(lazy_set,0,sizeof(lazy_set));
memset(lazy_add,0,sizeof(lazy_add));
makeTree(1,0,n);
int flag,l,r,v;
while(m--)
{
scanf("%d%d%d%d",&flag,&l,&r,&v);
update(1,0,n,l,r,v,flag);
printf("%d\n",tr[1]);
}
}
return 0;
}