hihocoder 1080 线段树:区间加法&赋值

1080 : 更为复杂的买卖房屋姿势
http://hihocoder.com/problemset/problem/1080

题面蛮好玩的,,也行是因为我玩模拟城市的缘故
这里写图片描述

修模板了

带两个操作的话,注意set和tag的顺序
每次down的时候先放set标记,再放tag标记
每次更新set的时候要把tag清空

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N =260000;
int n,m;
struct linetree{
    #define lc  (t<<1)
    #define rc  (t<<1^1)
    #define mid (l[t]+r[t]>>1)
    int l[N],r[N],M,tag[N],sum[N],len[N],Set[N];
    inline void build(int n){
        M=1; while(M<n)M<<=1; M--;//get M
        memset(sum,0,sizeof(sum));
        memset(tag,0,sizeof(tag));
        memset(Set,0,sizeof(Set));
        for (int i=1+M;i<=M*2+1;i++){//leaf
            if(i<=n+M)scanf("%d",&sum[i]);
            l[i] = r[i] = i-M ;
            len[i]=1;
        }
        for (int t=M;t>=1;t--){//fathers
            sum[t]=sum[lc]+sum[rc];
            l[t]=l[lc], r[t]=r[rc];
            len[t]=len[lc]+len[rc];
        }
    }
    inline void down(int t){
        if (t>M){Set[t]=tag[t]=0;return ;}//leaf node
        if (Set[t]){
            sum[lc]=Set[t]*len[lc];
            sum[rc]=Set[t]*len[rc];
            Set[lc]=Set[t];
            Set[rc]=Set[t];
            Set[t] = 0;
            tag[lc]=tag[rc]=0;//!!!
        }
        if (tag[t]){
            sum[lc]+=tag[t]*len[lc];
            sum[rc]+=tag[t]*len[rc];
            tag[lc]+=tag[t];
            tag[rc]+=tag[t];
            tag[t] = 0;
        }
    }
    inline void _tag(int t,int x){
        sum[t]+=x*len[t];
        tag[t]+=x;
    }
    inline void _set(int t,int x){
        sum[t]=x*len[t];
        Set[t]=x;
        tag[t]=0;//!!!
    }
    void change(int t,int L,int R,int x){
        if (L<=l[t]&&r[t]<=R){_tag(t,x);return;}
        down(t);
        if (L<=mid)change(lc,L,R,x);
        if (mid< R)change(rc,L,R,x);
        sum[t]=sum[lc]+sum[rc];
    }
    void set(int t,int L,int R,int x){
        if (L<=l[t]&&r[t]<=R){_set(t,x);return;}//in
        down(t);
        if (L<=mid)set(lc,L,R,x);
        if (mid< R)set(rc,L,R,x);
        sum[t]=sum[lc]+sum[rc];
    }
    int query(int t,int L,int R){
        if (L<=l[t]&&r[t]<=R)return sum[t];
        down(t);
        int ans = 0;
        if (L<=mid)ans+=query(lc,L,R);
        if (mid< R)ans+=query(rc,L,R);
        return ans;
    }
}T;

int main(){
    //freopen("fuck.in","r",stdin);
    int ord,l,r,x;
    for (;~scanf("%d%d",&n,&m);){
        n++;
        T.build(n);
        for (;m--;){
            scanf("%d%d%d%d",&ord,&l,&r,&x);
            l++;r++;
            if (ord) T.set(1,l,r,x);
            else T.change(1,l,r,x);
            printf("%d
",T.sum[1]);
        }
    }
    return 0;
}

自己写的时候还是不够细心,down里面set直接复制的tag的
然后+=忘了改成=,同时忘了清空tag标记

以后写数据结构还是要细(la)心(ban)啊

原文地址:https://www.cnblogs.com/cww97/p/7533977.html