题目链接:
题解思路:
题目中对区间修改有两个操作:
0 区间所有点增加v
1 区间所有点改为v
容易想到应该使用到两个懒惰标记 一个记录替换 一个记录增减
但这里会涉及到一个顺序问题 ,这里就需要考虑到 懒惰标记传递的策略:
如果出现替换标记 就应该把增减标记覆盖
如果同区间出现多个增减标记 则需要将标记叠加
代码:
#include<iostream> #include<cstdio> #include<cstring> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define maxn 100050 using namespace std; int w[maxn<<2]; int tag[maxn<<2][2]= {0}; void push_up(int rt) { w[rt]=w[rt<<1]+w[rt<<1|1]; } void push_down(int rt,int len) { if(tag[rt][1]) //替换标记 { tag[rt<<1][1]=tag[rt<<1|1][1]=tag[rt][1]; tag[rt<<1][0]=tag[rt<<1|1][0]=0; //子节点的增减标记清0 w[rt<<1]=(len-(len>>1))*tag[rt][1]; w[rt<<1|1]=(len>>1)*tag[rt][1]; tag[rt][1]=0; } if(tag[rt][0]) //增减标记 { tag[rt<<1][0]+=tag[rt][0]; //叠加 是+=不是=!!! tag[rt<<1|1][0]+=tag[rt][0]; //叠加 w[rt<<1]+=(len-(len>>1))*tag[rt][0]; w[rt<<1|1]+=(len>>1)*tag[rt][0]; tag[rt][0]=0; } } void build(int l,int r,int rt) { if(l==r) scanf("%d",&w[rt]); else { int m=(l+r)>>1; build(lson); build(rson); push_up(rt); } } void update(int op,int L,int R,int v,int l,int r,int rt) { if(L<=l&&R>=r) { if(op){ w[rt]=(r-l+1)*v; tag[rt][1]=v; tag[rt][0]=0; //增减标记清0 } else { w[rt]+=(r-l+1)*v; //叠加 tag[rt][0]+=v; } return ; } push_down(rt,r-l+1); int m=(l+r)>>1; if(L<=m) update(op,L,R,v,lson); if(R>m) update(op,L,R,v,rson); push_up(rt); } int main() { int n,q,op,l,r,v; scanf("%d%d",&n,&q); build(0,n,1); while(q--) { scanf("%d%d%d%d",&op,&l,&r,&v); update(op,l,r,v,0,n,1); printf("%d\n",w[1]); } return 0; }
时间: 2024-11-02 20:15:14