本题涉及到了线段数大多数基本操作。
因为只有20行,所以可以建20个线段树。
线段树最重要的两个函数:
pushdown 下移标记,并更新子节点数据。
pushup 由2个子节点数据更新父节点数据。
写法有很多,介绍一种不容易错的:
保证在设置标记的同时更新节点信息。即:在update给某节点打标记,以及pushdown下发标记时,都马上更新节点信息。
这样写的效果是pushup很短,直接更新,因为子节点的信息已经保证被更新过了,不需要考虑标记。相反在pushdown的时候要写很长,因为要直接更新子节点。
set操作会清空add标记。
因为只有20行,所以可以建20个线段树。
线段树最重要的两个函数:
pushdown 下移标记,并更新子节点数据。
pushup 由2个子节点数据更新父节点数据。
写法有很多,介绍一种不容易错的:
保证在设置标记的同时更新节点信息。即:在update给某节点打标记,以及pushdown下发标记时,都马上更新节点信息。
这样写的效果是pushup很短,直接更新,因为子节点的信息已经保证被更新过了,不需要考虑标记。相反在pushdown的时候要写很长,因为要直接更新子节点。
set操作会清空add标记。
代码:
//
// main.cpp
// 11992 Fast Matrix Operations
//
// Created by Baoli1100 on 15/3/14.
// Copyright (c) 2015年 Baoli1100. All rights reserved.
//
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 800005
#define INF 1000000000
struct Tree{
int Sum[maxn],Min[maxn],Max[maxn],add[maxn],Set[maxn];
int sumr,minr,maxr;
int op,y1,y2;
void init(){
memset(Sum,0,sizeof(Sum));
memset(add,0,sizeof(add));
memset(Set,-1,sizeof(Set));
memset(Min,0,sizeof(Min));
memset(Max,0,sizeof(Max));
};
void pushup(int rt){
int lc=rt<<1,rc=rt<<1|1;
Sum[rt]=Sum[lc]+Sum[rc];
Min[rt]=min(Min[lc],Min[rc]);
Max[rt]=max(Max[lc],Max[rc]);
}
void pushdown(int rt,int L,int R){
int lc=rt<<1,rc=rt<<1|1;
int M=(L+R)/2;
if(Set[rt]>=0){
Set[lc]=Set[rc]=Set[rt];
add[lc]=add[rc]=0;
Max[lc]=Max[rc]=Min[lc]=Min[rc]=Set[rt];
Sum[lc]=(M-L+1)*Set[rt];
Sum[rc]=(R-M)*Set[rt];
Set[rt]=-1;
}
if(add[rt]){
add[lc]+=add[rt];
add[rc]+=add[rt];
Max[lc]+=add[rt];Min[lc]+=add[rt];
Max[rc]+=add[rt];Min[rc]+=add[rt];
Sum[lc]+=add[rt]*(M-L+1);
Sum[rc]+=add[rt]*(R-M);
add[rt]=0;
}
}
void update(int rt,int L,int R,int v){
int lc=rt<<1,rc=rt<<1|1;
int M=(L+R)/2;
if(y1<=L&&y2>=R){
if(op==1){
add[rt]+=v;
Sum[rt]+=v*(R-L+1);
Max[rt]+=v;
Min[rt]+=v;
}
else {
Set[rt]=v;
add[rt]=0;
Max[rt]=Min[rt]=v;
Sum[rt]=v*(R-L+1);
}
}
else{
pushdown(rt,L,R);
if(y1<=M) update(lc,L,M,v);
if(y2>M) update(rc,M+1,R,v);
pushup(rt);
}
}
void Query(int rt,int L,int R){
int lc=rt<<1,rc=rt<<1|1;
int M=(L+R)/2;
if(y1<=L&&y2>=R){
sumr+=Sum[rt];
maxr=max(maxr,Max[rt]);
minr=min(minr,Min[rt]);
return;
}
else {
pushdown(rt,L,R);
if(y1<=M){
Query(lc,L,M);
}
if(y2>M) Query(rc,M+1,R);
pushup(rt);
}
}
}T[25];
int R,C,M;
int main(){
while(~scanf("%d%d%d",&R,&C,&M)){
for(int i=1;i<=R;i++){
T[i].init();
}
int op,x1,x2,y1,y2,v;
for(int i=1;i<=M;i++){
scanf("%d",&op);
if(op<3){
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&v);
for(int i=x1;i<=x2;i++){
T[i].y1=y1;T[i].y2=y2;T[i].op=op;
T[i].update(1,1,C,v);
}
}
else{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
int rmin=INF,rmax=-INF,rsum=0;
for(int i=x1;i<=x2;i++){
T[i].minr=INF;T[i].maxr=-INF;T[i].sumr=0;
T[i].y1=y1;T[i].y2=y2;
T[i].Query(1,1,C);
rmin=min(rmin,T[i].minr);
rmax=max(rmax,T[i].maxr);
rsum+=T[i].sumr;
}
printf("%d %d %d\n",rsum,rmin,rmax);
}
}
}
return 0;
}
/*
3 3 111
1 1 1 1 1 1
3 1 1 1 1
2 1 1 2 2 0
3 1 1 1 1
*/