题目大意:线段树的区间更改与查询,但是涉及到两种区间修改方式,一是给区间中的数全部加上一个数,二是将一个区间全部置为同一个数,然后询问整个区间和。
题目分析:处理好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 ",tr[1]); } } return 0; }