因为行数最多20行,所以可以每行建造一颗线段树
update时 set操作要清除add标记
但add操作不需要清楚set标记
maintain函数(用于维护节点)先考虑set再考虑add
query操作要综合考虑add和set
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<string>
#include<vector>
using namespace std;
const int maxn=4e5+10;
int r,c,m,ql,qr;
const int INF=1000000000;
int _min,_max,_sum;
struct intervalTree
{
int addv[maxn],setv[maxn],sum[maxn],minv[maxn],maxv[maxn];
void maintain(int node,int l,int r)
{
int lc=node<<1,rc=node<<1|1;
// sum[node]=minv[node]=maxv[node]=0;
if(r>l) {
sum[node]=sum[lc]+sum[rc];
minv[node]=min(minv[lc],minv[rc]);
maxv[node]=max(maxv[lc],maxv[rc]);
}
if(setv[node]>=0){
minv[node]=maxv[node]=setv[node];
sum[node]=setv[node]*(r-l+1);
}
if(addv[node]) {
minv[node]+=addv[node];
maxv[node]+=addv[node];
sum[node]+=addv[node]*(r-l+1);
}
}
void pushdown(int node)
{
int lc=node<<1,rc=node<<1|1;
if(setv[node]>=0) {
setv[lc]=setv[rc]=setv[node];
addv[lc]=addv[rc]=0;
setv[node]=-1;
}
if(addv[node]>0) {
addv[lc]+=addv[node];
addv[rc]+=addv[node];
addv[node]=0;
}
}
void updateset(int node,int l,int r,int v)
{
int lc=node<<1,rc=node<<1|1;
if(ql<=l&&qr>=r) {
setv[node]=v;
addv[node]=0;
}
else {
pushdown(node);
int m=l+(r-l)/2;
if(ql<=m) updateset(lc,l,m,v);
else maintain(lc,l,m);
if(qr>m) updateset(rc,m+1,r,v);
else maintain(rc,m+1,r);
}
maintain(node,l,r);
}
void updateadd(int node,int l,int r,int v)
{
int lc=node<<1,rc=node<<1|1;
if(ql<=l&&qr>=r) {
addv[node]+=v;
}
else {
pushdown(node);
int m=l+(r-l)/2;
if(ql<=m) updateadd(lc,l,m,v);
else maintain(lc,l,m);
if(qr>m) updateadd(rc,m+1,r,v);
else maintain(rc,m+1,r);
}
maintain(node,l,r);
}
void query(int node,int l,int r,int add)
{
if(setv[node]>=0) {
int v=add+addv[node]+setv[node];
_sum+=(min(qr,r)-max(l,ql)+1)*v;
_min=min(_min,v);
_max=max(_max,v);
}
else if(ql<=l&&qr>=r) {
_sum+=sum[node]+add*(r-l+1);
_min=min(_min,minv[node]+add);
_max=max(_max,maxv[node]+add);
}
else {
int m=l+(r-l)/2;
if(ql<=m)
query(node<<1,l,m,add+addv[node]);
if(qr>m)
query(node<<1|1,m+1,r,add+addv[node]);
}
}
};
intervalTree tree[25];
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
while(scanf("%d%d%d",&r,&c,&m)!=EOF) {
memset(tree,0,sizeof tree);
for(int i = 1; i <= r;++i) {
memset(tree[i].setv, -1, sizeof(tree[i].setv));
tree[i].setv[1] = 0;
}
int op,x1,x2,v;
while(m--) {
_sum=0;
_min=INF;
_max=0;
scanf("%d%d%d%d%d",&op,&x1,&ql,&x2,&qr);
//if(x1>x2) swap(x1,x2);
if(op==1||op==2) {
scanf("%d",&v);
if(op==1) {
for(int i = x1;i<=x2;++i) {
tree[i].updateadd(1,1,c,v);
}
}
else {
for(int i = x1;i<=x2;++i) {
tree[i].updateset(1,1,c,v);
}
}
}
else {
for(int i=x1;i<=x2;++i) {
tree[i].query(1,1,c,0);
}
printf("%d %d %d\n",_sum,_min,_max);
}
}
}
return 0;
}