hiho1080 更为复杂的买卖房屋姿势

题目链接:

hihocoder1080




题解思路:

题目中对区间改动有两个操作:

0   区间全部点添加v

1   区间全部点改为v


easy想到应该使用到两个懒惰标记  一个记录替换  一个记录增减

但这里会涉及到一个顺序问题 ,这里就须要考虑到 懒惰标记传递的策略:

假设出现替换标记 就应该把增减标记覆盖

假设同区间出现多个增减标记 则须要将标记叠加



代码:

#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 ",w[1]); } return 0; }



原文地址:https://www.cnblogs.com/llguanli/p/6812793.html