线段树 add操作(惰性标记下推)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define lson l,m,rt<<1
#define rson m+1,r,(rt<<1|1)
#define INF  1000000100

const int maxn = 1000010;
int sum[maxn<<2],MIN[maxn<<2],MAX[maxn<<2],add[maxn<<2];
void pushUP(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
MAX[rt]=max(MAX[rt<<1],MAX[rt<<1|1]);
MIN[rt]=min(MIN[rt<<1],MIN[rt<<1|1]);
}
void maintain(int l,int r,int rt){
sum[rt]=MIN[rt]=MAX[rt]=0;
if(r>l) pushUP(rt);
sum[rt]+=add[rt]*(r-l+1); MAX[rt]+=add[rt]; MIN[rt]+=add[rt];
}
void pushDOWN(int l,int r,int rt){
if(l==r) return ;
if(add[rt]){
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
add[rt]=0;
}
}
void build(int l,int r,int rt){
add[rt]=0;
if(l==r){
    scanf("%d",&sum[rt]);
    add[rt]=MAX[rt]=MIN[rt]=sum[rt];
    return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushUP(rt);
}
int ql,qr,addv;
void update(int l,int r,int rt){
if(ql<=l&&r<=qr){
    add[rt]+=addv;
    sum[rt]+=addv*(r-l+1);
    MIN[rt]+=addv;
    MAX[rt]+=addv;
    return ;
}
pushDOWN(l,r,rt);
int m=(l+r)>>1;
if(ql<=m) update(lson);
if(qr >m) update(rson);
pushUP(rt);
}
int sum_,min_,max_;
void query(int l,int r,int rt,int ADD){
if(ql<=l&&r<=qr){
    sum_+=sum[rt]+ADD*(r-l+1);
    min_= min(min_,ADD+MIN[rt]);
    max_= max(max_,ADD+MAX[rt]);
}
else {
int m=(l+r)>>1;
if(ql<=m) query(lson,ADD+add[rt]);
if(qr >m) query(rson,ADD+add[rt]);
}
}
int main()
{
    void show(int l,int r,int rt);
    int n,Q;
    while(scanf("%d %d",&n,&Q)==2){
        build(1,n,1);
        while(Q--){
            int cmd;
            scanf("%d",&cmd);
            if(cmd==1){
                scanf("%d %d %d",&ql,&qr,&addv);
                update(1,n,1);
            }
            else {
                scanf("%d %d",&ql,&qr);
                sum_=0; min_=INF; max_=-INF;
                query(1,n,1,0);
                cout<<sum_<<" "<<min_<<" "<<max_<<endl;
            }
           // show(1,n,1);
        }
    }
    return 0;
}
void show(int l,int r,int rt){
if(l==r){
cout<<"L-->"<<" "<<l<<" "<<"R-->"<<" "<<r<<" "<<sum[rt]<<" "<<add[rt]<<endl;
   return ;
}
int m=(l+r)>>1;
show(lson);
show(rson);
cout<<"L-->"<<" "<<l<<" "<<"R-->"<<" "<<r<<" "<<sum[rt]<<" "<<add[rt]<<endl;
}

你可能感兴趣的:(线段树 add操作(惰性标记下推))