题意:给你一个一开始全为0的矩阵,有三种操作,子矩阵全部增加一个数,子矩阵替换一个数,查询子矩阵之和和最大最小值
思路:显然的线段树,留意到这个矩阵最多只有20行,所以每一行都建一颗线段树即可
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn = 1000010;
const int INF = 1e9;
#define lson i*2,l,m
#define rson i*2+1,m+1,r
int r,c,m;
int amax[22],amin[22],asum[22];
int setv[maxn*5],addv[maxn*5],sum[maxn*5],minv[maxn*5],maxv[maxn*5];
void build(int k,int i,int l,int r)
{
int t = k*4*c;
setv[t+i]=-1;
addv[t+i]=sum[t+i]=minv[t+i]=maxv[t+i]=0;
if (l==r)
return;
int m = (l+r)>>1;
build(k,lson);
build(k,rson);
}
void PushDown(int k,int i,int l,int r)
{
int t = k*4*c;
int m = (l+r)>>1;
if (setv[t+i]!=-1)
{
if (l!=r)
{
addv[t+i*2]=addv[t+i*2+1]=0;
setv[t+i*2]=setv[t+i*2+1]=setv[t+i];
sum[t+i*2]=setv[t+i]*(m-l+1);
sum[t+i*2+1]=setv[t+i]*(r-m);
maxv[t+i*2]=minv[t+i*2]=maxv[t+i*2+1]=minv[t+i*2+1]=setv[t+i];
}
setv[t+i]=-1;
}
if (addv[t+i]>0)
{
if (l!=r)
{
addv[t+i*2]+=addv[t+i];
addv[t+i*2+1]+=addv[t+i];
sum[t+i*2]+=addv[t+i]*(m-l+1);
maxv[t+i*2]+=addv[t+i];
minv[t+i*2]+=addv[t+i];
sum[t+i*2+1]+=addv[t+i]*(r-m);
maxv[t+i*2+1]+=addv[t+i];
minv[t+i*2+1]+=addv[t+i];
}
addv[t+i]=0;
}
}
void PushUp(int k,int i,int l,int r)
{
int t = k*4*c;
sum[t+i]=sum[t+i*2]+sum[t+i*2+1];
maxv[t+i]=max(maxv[t+i*2],maxv[t+i*2+1]);
minv[t+i]=min(minv[t+i*2],minv[t+i*2+1]);
}
void update_add(int k,int ql,int qr,int v,int i,int l,int r)
{
int t = k*4*c;
if (ql<=l && r<=qr)
{
addv[t+i]+=v;
sum[t+i]+=v*(r-l+1);
maxv[t+i]+=v;
minv[t+i]+=v;
return;
}
PushDown(k,i,l,r);
int m = (l+r)>>1;
if (ql<=m)
update_add(k,ql,qr,v,lson);
if (m<qr)
update_add(k,ql,qr,v,rson);
PushUp(k,i,l,r);
}
void update_set(int k,int ql,int qr,int v,int i,int l,int r)
{
int t = k*4*c;
if (ql<=l && qr>=r)
{
setv[t+i]=v;
addv[t+i]=0;
sum[t+i]=v*(r-l+1);
maxv[t+i]=minv[t+i]=v;
return;
}
PushDown(k,i,l,r);
int m = (l+r)>>1;
if (ql<=m)
update_set(k,ql,qr,v,lson);
if (m<qr)
update_set(k,ql,qr,v,rson);
PushUp(k,i,l,r);
}
void query(int k,int ql,int qr,int i,int l,int r)
{
int t =4*c*k;
if (ql<=l && qr>=r)
{
asum[k]+=sum[t+i];
amin[k]=min(amin[k],minv[t+i]);
amax[k]=max(amax[k],maxv[t+i]);
return;
}
PushDown(k,i,l,r);
int m = (l+r)>>1;
if (ql<=m)
query(k,ql,qr,lson);
if (m<qr)
query(k,ql,qr,rson);
}
int main()
{
while (scanf("%d%d%d",&r,&c,&m)!=EOF)
{
for (int i = 1;i<=r;i++)
build(i,1,1,c);
while (m--)
{
int op,x1,x2,y1,y2,v;
scanf("%d%d%d%d%d",&op,&x1,&y1,&x2,&y2);
if (op!=3)
scanf("%d",&v);
if (op==1)
{
for (int i = x1;i<=x2;i++)
update_add(i,y1,y2,v,1,1,c);
}
else if (op==2)
{
for (int i = x1;i<=x2;i++)
update_set(i,y1,y2,v,1,1,c);
}
else if (op==3)
{
memset(asum,0,sizeof(asum));
for (int i = 0;i<=r;i++)
{
amax[i]=-INF;
amin[i]=INF;
}
int sum_v=0,max_v=-INF,min_v=INF;
for (int i = x1;i<=x2;i++)
{
query(i,y1,y2,1,1,c);
sum_v+=asum[i];
max_v=max(max_v,amax[i]);
min_v=min(min_v,amin[i]);
}
printf("%d %d %d\n",sum_v,min_v,max_v);
}
}
}
}