这道题要求同时实现快速_求区间最小值,最大值,区间和,区间成段修改,区间成段增减的线段树。
我把刘汝佳的风格和not only but successful 线段树结合在一起搭了一个模板,原理还没理解 。。 刘汝佳的query查询方式+ not only sucess的build 建树。
#include<stdio.h>
#include<algorithm>
#include<string.h>
typedef long long ll;
using namespace std ;
const int INF=1000000002;
const int inf=-INF;
const int maxnode=1000001<<2;
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
/* 符号说明*/
int L,R;
/*
查询区间和修改区间表示为[l ,R] <--声明为全局变量
*/
int _min,_max,_sum; /*查询区间最小值,最大值,和 */
int v; /* Update 的改变量 区间增加 v,区间改成 v */
int n,m,op,num;
struct setree{
int sumv[maxnode],addv[maxnode],minv[maxnode],maxv[maxnode], setv[maxnode];
void PushUp(int rt,int l,int r){
//sumv[rt]=minv[rt]=maxv[rt]=0;
if(r>l){
sumv[rt]=sumv[rt<<1]+sumv[rt<<1|1];
maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);
minv[rt]=min(minv[rt<<1],minv[rt<<1|1]);
}
if(setv[rt]>=0){
minv[rt]=maxv[rt]=setv[rt] ; sumv[rt]=(r-l+1)*setv[rt];
}
if(addv[rt]){
sumv[rt]+=addv[rt]*(r-l+1);
minv[rt]+=addv[rt];
maxv[rt]+=addv[rt];
}
}
void PushDown(int rt){
if(setv[rt]>=0){
setv[rt<<1]=setv[rt<<1|1]=setv[rt];
addv[rt<<1]=addv[rt<<1|1]=0;
setv[rt]=-1;
}
if(addv[rt]){
addv[rt<<1]+=addv[rt];
addv[rt<<1|1]+=addv[rt];
addv[rt]=0;
}
}
void build(int rt,int l,int r){
addv[rt]=0;
// 注意 setv[1]=0;
if(l==r) {scanf("%I64d",&sumv[rt]);
addv[rt]=minv[rt]=maxv[rt]=sumv[rt];
return ;
}
int m=l+(r-l)/2;
build(lson);
build(rson);
sumv[rt]=sumv[rt<<1]+sumv[rt<<1|1];
}
void update(int rt,int l,int r){
if(L<=l&&r<=R){
if(op==1) addv[rt]+=v;
else{
setv[rt]=v; addv[rt]=0;
}
}else{
PushDown(rt);
int m=l+(r-l)/2; // m==(R+L)>>1;
if(L<=m) update(lson);
else PushUp(lson);
if(m<R) update(rson);
else PushUp(rson);
}
PushUp(rt,l,r);
}
void query(int rt,int l,int r,int add){
if(setv[rt]>=0){
int v=setv[rt]+add+addv[rt];
_sum +=v*(min(R,r)-max(l,L)+1);
_min =min(_min,v);
_max =max(_max,v);
}else if(L<=l&&r<=R){
_sum+=sumv[rt]+add*(r-l+1);
_min =min(_min,minv[rt]+add);
_max =max(_max,maxv[rt]+add);
}else {
int m=l+(r-l)/2;
if(L<=m) query(lson,add+addv[rt]);
if(m<R) query(rson,add+addv[rt]);
}
}
}t[21];
int cnt=0;
int main(){
void debug();
//freopen("F:\\123.txt","r",stdin);
while(scanf("%d%d%d",&n,&m,&num)!=EOF){
int x1,x2,y1,y2;
for(int i=1;i<=n;i++){
memset(t[i].sumv ,0,sizeof(t[i].sumv ));
memset(t[i].maxv ,0,sizeof(t[i].maxv ));
memset(t[i].minv ,0,sizeof(t[i].minv ));
memset(t[i].addv, 0,sizeof(t[i].addv ));
memset(t[i].setv ,-1,sizeof(t[i].setv ));
t[i].setv[1]=0;
}
for(int i=0;i<num;i++){
//debug();
scanf("%d%d%d%d%d",&op,&x1,&L,&x2,&R);
if(op==1||op==2){
scanf("%d",&v);
for(int i=x1;i<=x2;i++){
t[i].update(1,1,m);
}
}else if(op==3){
_sum=0; _max=inf; _min=INF;
for(int i=x1;i<=x2;i++){
t[i].query(1,1,m,0);
}
printf("%d %d %d\n",_sum,_min,_max);
}else{
}
}
}
return 0;
}
void debug(){
printf(" %d------------\n",cnt++);
for(int xx1=1;xx1<=4;xx1++){
for(int yy1=1;yy1<=4;yy1++){
_sum=0;
L=yy1,R=yy1;
t[xx1].query(1,1,m,0);
printf("%d ",_sum);
}
printf("\n");
}
printf("--------------\n");
}