uva 11992
题意:
给定一个r*c(r<=20,r*c<=1e6)的矩阵,其元素都是0,现在对其子矩阵进行操作。
1 x1 y1 x2 y2 val 表示将(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素add上val;
2 x1 y1 x2 y2 val 表示将(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素set为val;
3 x1 y1 x2 y2 val 表示输出(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素的sum,最大最小值
链接:
https://vjudge.net/contest/203644#problem/B
题解:
显然这两个操作是可以用线段树来维护的,但关键在于二维
注意到n<=20 ,所以可以考虑对每一行对列进行线段树维护
另外修改为v和增加v两个操作的同时存在
要注意:修改为v要清空增加v 并且先处理修改为v后处理增加v
代码:
#include <bits/stdc++.h>
#define mid (h+t)/2
using namespace std;
struct re{int a,b,c;} tmp;
struct ree{int h,t,x1,x2,x3,lazy1,lazy2;}p[22][300000];
void build(int hh,int x,int h,int t)
{
p[hh][x].h=h; p[hh][x].t=t; p[hh][x].x3=0;
if (h==t)
{
return;
}
build(hh,x*2,h,mid); build(hh,x*2+1,mid+1,t);
};
void down(int hh,int x)
{
if (p[hh][x].lazy2!=0)
{
p[hh][x].x1=(p[hh][x].t-p[hh][x].h+1)*p[hh][x].lazy2;
p[hh][x].x2=p[hh][x].lazy2;
p[hh][x].x3=p[hh][x].lazy2;
p[hh][x*2].lazy2=p[hh][x].lazy2;
p[hh][x*2+1].lazy2=p[hh][x].lazy2;
p[hh][x*2].lazy1=p[hh][x*2+1].lazy1=0;
p[hh][x].lazy2=0;
}
p[hh][x].x1+=(p[hh][x].t-p[hh][x].h+1)*p[hh][x].lazy1;
p[hh][x].x2+=p[hh][x].lazy1;
p[hh][x].x3+=p[hh][x].lazy1;
p[hh][x*2].lazy1+=p[hh][x].lazy1;
p[hh][x*2+1].lazy1+=p[hh][x].lazy1;
p[hh][x].lazy1=0;
};
void change1(int hh,int x,int sum,int h,int t)
{
down(hh,x);
if (h>p[hh][x].t || p[hh][x].h>t) return;
if (h<=p[hh][x].h && p[hh][x].t<=t)
{
p[hh][x].lazy1+=sum,down(hh,x);
return;
}
change1(hh,x*2,sum,h,t);
change1(hh,x*2+1,sum,h,t);
p[hh][x].x1=p[hh][x*2].x1+p[hh][x*2+1].x1;
p[hh][x].x2=max(p[hh][x*2].x2,p[hh][x*2+1].x2);
p[hh][x].x3=min(p[hh][x*2].x3,p[hh][x*2+1].x3);
};
void change2(int hh,int x,int sum,int h,int t)
{
down(hh,x);
if (h>p[hh][x].t || p[hh][x].h>t) return;
if (h<=p[hh][x].h && p[hh][x].t<=t)
{
p[hh][x].lazy1=0,p[hh][x].lazy2=sum,down(hh,x);
return;
}
change2(hh,x*2,sum,h,t);
change2(hh,x*2+1,sum,h,t);
p[hh][x].x1=p[hh][x*2].x1+p[hh][x*2+1].x1;
p[hh][x].x2=max(p[hh][x*2].x2,p[hh][x*2+1].x2);
p[hh][x].x3=min(p[hh][x*2].x3,p[hh][x*2+1].x3);
};
re query(int hh,int x,int h,int t)
{
re tmp,tmp1,tmp2;
tmp.a=0; tmp.b=0; tmp.c=1000000000;
down(hh,x);
if (h>p[hh][x].t || p[hh][x].h>t) return(tmp);
if (h<=p[hh][x].h && p[hh][x].t<=t)
{
tmp.a=p[hh][x].x1,tmp.b=p[hh][x].x2,tmp.c=p[hh][x].x3;
return(tmp);
}
tmp1=query(hh,x*2,h,t); tmp2=query(hh,x*2+1,h,t);
tmp.a=tmp1.a+tmp2.a; tmp.b=max(tmp1.b,tmp2.b); tmp.c=min(tmp1.c,tmp2.c);
return(tmp);
};
int main()
{
int n,m,k,a1,a2,a3,a4,a5,a6;
while (cin>>n>>m>>k)
{
memset(p,0,sizeof(p));
for (int i=1; i<=n;i++)
build(i,1,1,m);
for (int i=1;i<=k;i++)
{
cin>>a1>>a2>>a3>>a4>>a5;
if (a1==1)
{
cin>>a6;
for (int j=a2;j<=a4;j++)
change1(j,1,a6,a3,a5);
}
if (a1==2)
{
cin>>a6;
for (int j=a2;j<=a4;j++)
change2(j,1,a6,a3,a5);
}
if (a1==3)
{
int sum1=0,maxn=0,minn=1000000000;
for (int j=a2;j<=a4;j++)
{
tmp=query(j,1,a3,a5);
sum1+=tmp.a;
maxn=max(maxn,tmp.b);
minn=min(minn,tmp.c);
}
cout<<sum1<<" "<<minn<<" "<<maxn<<endl;
}
}
}
return(0);
}