模板_线段树

最小值查询

int ql,qr;//查询[ql,qr]最小值
int query(int o,int l,int r){
    int m=l+(l+r)/2,ans=INF;
    if(ql<=l&&qr>=r) return minv[o];//包含
    if(ql<=m) ans=min(ans,query(o*2,l,m));//left
    if(mmin(ans,query(o*2+1,m+1,r));//right
    return ans;
}

点修改

int p,v;
void updata(int o,int l,int r){
    int m=l+(l+r)/2;
    if(l==r) minv[o]=v;//叶节点
    else{
        if(p<=m) updata(o*2,l,m);//左子树
        else updata(o*2+1,m+1,r);//右子树
        minv[o]=min(minv[o*2],minv[o*2+1]);
    }
}

信息维护

void maintain(int o,int l,int r){
    int lc=o*2,rc=o*2+1;
    sumv[o]=minv[o]=maxv[o]=0;
    if(r>l){
        sumv[o]=sumv[lc,rc];
        minv[o]=min(minv[lc],minv[rc]);
        maxv[o]=max(maxv[lc],maxv[rc]);
    }
    minv[o]+=addv[o];maxv[o]+=addv[o];sumv[o]+=addv*(r-l+1);
}

add操作

void updata(int o,int l,int r){
    int lc=o*2,rc=o*2+1;
    if(y1<=l&&y2>=r){
        addv[o]+=v;
    }
    else{
        int m=l+(l+r)/2;
        if(y1<=m) updata(lc,l,m);
        if(y2>m) updata(rc,m+1,r); 
    }
    maintain(o,l,r);//维护区间信息
}

区间查询

int _min,_max,_sum;
void query(int o,int l,int r,int add){
    if(y1<=l&&r2>=r){
        _sum+=sumv[o]+add*(r-l+1);
        _min=min(_min,minv[o]+add);
        _max=max(_max,maxv[o]+add);
    }
    else{
        int m=l+(l+r)/2;
        if(y1<=m) query(o*2,l,m,add+addv[o]);
        if(y2>m) query(o*2+1,m+1,r,add+addv[o]);
    }
}

区间全部修改

void updata(int o,int l,int r){
    int lc=o*2,rc=lc+1;
    if(y1<=l&&y2>=r){
        setv[o]=v;
    }else{
        pushdown(o);
        int m=l+(l+r)/2;
        if(y1<=m) updata(lc,l,m);
        if(y2>m) updata(rc,m+1,r);
    }
    maintain(o,l,r);
}

标记传递

void pushdown(o){
    int lc=o*2,rc=lc+1;
    if(setv[o]>=0){
        setv[lc]=setv[rc]=setv[o];
        setv[o]=-1;//清除标记
    }
}

set的区间查询

int _min,_max,_sum;
void query(int o,int l,int r){
    if(setv[o]>=0){
        _sum+=setv[o]*(min(r,y2)-max(l,y1)+1);
        _min=min(_min,setv[o]);
        _max=max(_max,setv[o]);
    }
    else if(y1<=l&&r2>=r){
        _sum+=sumv[o];
        _min=min(_min,minv[o]);
        _max=max(_max,maxv[o]);
    }
    else{
        int m=l+(l+r)/2;
        if(y1<=m) query(o*2,l,m);
        if(y2>m) query(o*2+1,m+1,r);
    }
}

你可能感兴趣的:(线段树,模板)