题意:一个r*c的矩阵,初始值全部为0,后进行三种操作,
1 子矩阵[x1,y1]--[x2,y2]所有元素+v,
2 子矩阵[x1,y1][x2,y2]所有元素变为v
3 输出子矩阵[x1,y1][x2,y2]的所有元素和,最小值,最大值
思路:一个线段树,不知道哪里来的条件是r<=20..所以第一维可以直接暴力循环更改查找。。单独的修改区间元素值和区间加值。都是会的,两个连在一起也不是很难,就是有点复杂。。。函数嵌套
感想:到现在不知道条件r<=20哪里来的。。。当然这题是看的题解,不然真的不知道怎么做。。。最后,这个题按着r<=20的前提来暴力做并不很难,就是复杂,所以代码就看了一下,也不敲了,加了两句注释。。。
代码:
#include<bits/stdc++.h>
#define MAX 3000100
using namespace std;
struct node
{
int l,r;
int mini,maxi,sum;
int add,set;
}a[MAX];
int anssum,ansmin,ansmax,r,c,m;
const int inf=1000000009;
void built(int l,int r,int index)///建树
{
a[index].l=l;a[index].r=r;a[index].add=0;a[index].set=-1;a[index].sum=a[index].mini=a[index].maxi=0;
if(l==r)
return;
int mid=l+(r-l)/2;
built(l,mid,index<<1);built(mid+1,r,index<<1|1);
}
void pushdown(int index)///更新子节点
{
if(a[index].l>=a[index].r)
return;
if(a[index].set!=-1)
{
a[index<<1].set=a[index<<1|1].set=a[index].set;
a[index<<1].mini=a[index<<1|1].mini=a[index].set;
a[index<<1].maxi=a[index<<1|1].maxi=a[index].set;
a[index<<1].add=a[index<<1|1].add=0;
a[index<<1].sum=(a[index<<1].r-a[index<<1].l+1)*a[index].set;
a[index<<1|1].sum=(a[index<<1|1].r-a[index<<1|1].l+1)*a[index].set;
}
if(a[index].add>0)
{
int ita=a[index].add;
a[index<<1].add+=ita;a[index<<1|1].add+=ita;
a[index<<1].mini+=ita;a[index<<1|1].mini+=ita;
a[index<<1].maxi+=ita;a[index<<1|1].maxi+=ita;
a[index<<1].sum+=ita*(a[index<<1].r-a[index<<1].l+1);
a[index<<1|1].sum+=ita*(a[index<<1|1].r-a[index<<1|1].l+1);
}
}
void maintain(int index)///更新当前节点
{
if(a[index].l>=a[index].r)
return;
a[index].maxi=max(a[index<<1].maxi,a[index<<1|1].maxi);
a[index].mini=min(a[index<<1].mini,a[index<<1|1].mini);
a[index].sum=a[index<<1].sum+a[index<<1|1].sum;
}
void updateSet(int L,int R,int val,int index) ///区间赋新值,更新树
{
if(a[index].l==L&&a[index].r==R)
{
a[index].set=val;
a[index].maxi=val;
a[index].mini=val;
a[index].add=0;
a[index].sum=(a[index].r-a[index].l+1)*val;
return;
}
pushdown(index);
a[index].set=-1;
a[index].add=0;
int mid=a[index].l+(a[index].r-a[index].l)/2;
if(R<=mid)
updateSet(L,R,val,index<<1);
else if(L>mid)
updateSet(L,R,val,index<<1|1);
else
{
updateSet(L,mid,val,index<<1);
updateSet(mid+1,R,val,index<<1|1);
}
maintain(index);
}
void updateAdd(int L,int R,int val,int index)///区间加值,更新树
{
if(a[index].l==L&&a[index].r==R)
{
a[index].add+=val;
a[index].maxi+=val;
a[index].mini+=val;
a[index].sum+=(a[index].r-a[index].l+1)*val;
return ;
}
pushdown(index);
a[index].set=-1;
a[index].add=0;
int mid=a[index].l+(a[index].r-a[index].l)/2;
if(R<=mid)
updateAdd(L,R,val,index<<1);
else if(L>mid)
updateAdd(L,R,val,index<<1|1);
else
{
updateAdd(L,mid,val,index<<1);
updateAdd(mid+1,R,val,index<<1|1);
}
maintain(index);
}
void Query(int L,int R,int index)///查找区间最值与和
{
if(a[index].l==L&&a[index].r==R)
{
anssum+=a[index].sum;
ansmin=min(ansmin,a[index].mini);
ansmax=max(ansmax,a[index].maxi);
return;
}
pushdown(index);
a[index].set=-1;
a[index].add=0;
int mid=a[index].l+(a[index].r-a[index].l)/2;
if(R<=mid)
Query(L,R,index<<1);
else if(L>mid)
Query(L,R,index<<1|1);
else
{
Query(L,mid,index<<1);
Query(mid+1,R,index<<1|1);
}
maintain(index);
}
int main()
{
while(scanf("%d%d%d",&r,&c,&m)!=EOF)
{
built(1,r*c,1);
int op,x1,x2,y1,y2,val;
while(m--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&val);
for(int i=x1;i<=x2;i++)
updateAdd((i-1)*c+y1,(i-1)*c+y2,val,1);
}
else if(op==2)
{
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&val);
for(int i=x1;i<=x2;i++)
updateSet((i-1)*c+y1,(i-1)*c+y2,val,1);
}
else
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
anssum=0;ansmin=inf;ansmax=-inf;
for(int i=x1;i<=x2;i++)
Query((i-1)*c+y1,(i-1)*c+y2,1);
printf("%d %d %d\n",anssum,ansmin,ansmax);
}
}
}
return 0;
}