[tem]线段树(白书版)

个人感觉有点坑

add用的标记永久化

set用的标记下传

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define lson o<<1,l,m
#define rson (o<<1)+1,m+1,r
#define ls o<<1
#define rs (o<<1)+1
using namespace std;
const int N=1e4,INF=1e9;

int minv[N<<2],maxv[N<<2],sumv[N<<2];
int addv[N<<2],setv[N<<2];
int ql,qr,p,v;

//point     
int queryMin(int o,int l,int r){
    int m=l+((r-l)>>1),ans=INF;
    if(ql<=l&&r<=qr) return minv[o];
    if(ql<=m) ans=min(ans,queryMin(lson));
    if(m+1<=qr) ans=min(ans,queryMin(rson));
    return ans;
}

void change(int o,int l,int r){
    int m=l+((r-l)>>1);
    if(l==r)
        minv[o]=v;
    else{
        if(p<=m) change(lson);
        else change(rson);
        minv[o]=min(minv[ls],minv[rs]);
    }
}


//add   
int _min,_max,_sum;
void maintain(int o,int l,int r){
    sumv[o]=minv[o]=maxv[o]=0;//!!
    if(l<r){
        sumv[o]=sumv[ls]+sumv[rs];
        minv[o]=min(minv[ls],minv[rs]);
        maxv[o]=max(maxv[ls],maxv[rs]);
    }
    minv[o]+=addv[o];
    maxv[o]+=addv[o];
    sumv[o]+=addv[o]*(r-l+1);
}

void addRange(int o,int l,int r){
    if(ql<=l&&r<=qr)
        addv[o]+=v;
    else{
        int m=(r+l)>>1;
        if(ql<=m) addRange(lson);
        if(m+1<=qr) addRange(rson);
    }
    maintain(o,l,r);
}

void queryRange(int o,int l,int r,int add){
    if(ql<=l&&r<=qr){
        _sum+=sumv[o]+add*(r-l+1);
        _min=min(_min,minv[o]+add);
        _max=max(_max,maxv[o]+add);
    }else{
        int m=(r+l)>>1;
        if(ql<=m) queryRange(lson,add+addv[o]);
        if(m+1<=qr) queryRange(rson,add+addv[o]);
    }
}

//set
void mt(int o,int l,int r){
    if(setv[o]>=0){
        sumv[o]=setv[o]*(r-l+1);
        minv[o]=maxv[o]=setv[o];
    }else if(l<r){
        sumv[o]=sumv[ls]+sumv[rs];
        minv[o]=min(minv[ls],minv[rs]);
        maxv[o]=max(maxv[ls],maxv[rs]);
    }
}

void pushDown(int o){
    if(setv[o]>=0){
        setv[ls]=setv[rs]=setv[o];
        setv[o]=-1;
    }
}

void setRange(int o,int l,int r){
    if(ql<=l&&r<=qr) setv[o]=v;
    else {
        pushDown(o);
        int m=(r+l)>>1;
        if(ql<=m) setRange(lson); else mt(lson);
        if(m+1<=qr) setRange(rson); else mt(rson);
    }
    mt(o,l,r);
}

void queryRange(int o,int l,int r){
    if(setv[o]>=0){
        _sum+=setv[o]*(r-l+1);
        _min=min(_min,setv[o]);
        _max=max(_max,setv[o]);
    }else if(ql<=l&&r<=qr){
        _sum+=sumv[o];
        _min=min(_min,minv[o]);
        _max=max(_max,maxv[o]);
    }else{
        int m=(r+l)>>1;
        if(ql<=m) queryRange(lson);
        if(m+1<=qr) queryRange(rson);
    }
}

int n,t;
int main(int argc, const char * argv[]) {

//freopen("in.txt","r",stdin);
//freopen("2.txt","w",stdout);
    
    cin>>n>>t;
    for(int i=1;i<=n;i++){
        cin>>v;
        ql=qr=i;
        addRange(1,1,n);
    }

//    for(int i=1;i<=n<<1;i++) printf("%d %d %d %d
",i,sumv[i],minv[i],maxv[i]);
    
    while(t--){
        int flag;
        cin>>flag;
        if(flag==1){
            cin>>ql>>qr;
            _sum=0;_min=INF;_max=-INF;
            queryRange(1,1,n,0);    
            printf("%d
",_sum);
        }else{
            cin>>ql>>qr>>v;
            addRange(1,1,n);
            _sum=0;_min=INF;_max=-INF;
            queryRange(1,1,n,0);
            printf("%d
",_sum);
        }
    }

    return 0;
}
原文地址:https://www.cnblogs.com/candy99/p/5745223.html