差点忘记还有这么一个线段树的题目,白书上的最后一个例题了,也是足见其难度啊,和一般的题目就是不一样,这个需要考虑的是set和add两种情况同时存在的情况了,这个需要考虑的就是当add先在某一段区间标记了,那么如果下一次当该区间又标记了set的话,实际上前面做到add就没用了,可以直接被抹去了,而如果在set之后又来了一次的set的话,那样的话两者都需要保留下来,那么难点就来了,在pushdown这里的话,肯定需要先判读set标记了,如果set存在的话那么对其左右子树进行各种操作了,特别的需要对左右子节点的add标志要清零,因为下面对左右子节点的set要进行操作了那就和前面说道的一样,set出现,那么之前的add都不算数了,其他的各种指标只要合理操作即可了。
这题还是有点难度的,参考了这篇博文:http://blog.csdn.net/a601025382s/article/details/38356535
还有就是我的这里的代码的写法不如上面博客的,因为写惯了不是结构体的写法,在这个多指标的情况下,其实还是一开始就直接写结构体会来的更加方便一些。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define mid int m = (l + r)>>1
const int maxn=10e6+5;
int r,c,m,tag,x1,x2,y1,y2,v;
int adds[maxn<<2],sets[maxn<<2],sum[maxn<<2],maxs[maxn<<2],mins[maxn<<2];
struct node
{
int sum,maxs,mins;
};
void build(int l,int r,int rt)
{
adds[rt]=sets[rt]=sum[rt]=maxs[rt]=mins[rt]=0;
if(l==r)
return ;
mid;
build(lson);
build(rson);
}
void pushdown(int l,int r,int rt)
{
if(sets[rt]!=0)//当有两个标记时,必定是add要在set之后做的
{
adds[rt*2]=adds[rt*2+1]=0;
sets[rt*2]=sets[rt*2+1]=sets[rt];
mins[rt*2]=mins[rt*2+1]=maxs[rt*2]=maxs[rt*2+1]=sets[rt];
mid;
sum[rt*2]=(m-l+1)*sets[rt];
sum[rt*2+1]=(r-m)*sets[rt];
sets[rt]=0;
}
if(adds[rt]!=0)
{
adds[rt*2]+=adds[rt];
adds[rt*2+1]+=adds[rt];
maxs[rt*2]+=adds[rt];
maxs[rt*2+1]+=adds[rt];
mins[rt*2]+=adds[rt];
mins[rt*2+1]+=adds[rt];
mid;
sum[rt*2]+=(m-l+1)*adds[rt];
sum[rt*2+1]+=(r-m)*adds[rt];
adds[rt]=0;
}
}
void update_add(int l,int r,int rt,int x,int y,int z)
{
if(x<=l&&y>=r)
{
adds[rt]+=z;
maxs[rt]+=z;
mins[rt]+=z;
sum[rt]+=(r-l+1)*z;
return ;
}
mid;
pushdown(l,r,rt);
if(x<=m) update_add(lson,x,y,z);
if(y>m) update_add(rson,x,y,z);
maxs[rt]=max(maxs[rt*2],maxs[rt*2+1]);
mins[rt]=min(mins[rt*2],mins[rt*2+1]);
sum[rt]=sum[rt*2]+sum[rt*2+1];
}
void update_set(int l,int r,int rt,int x,int y,int z)
{
if(x<=l&&y>=r)
{
adds[rt]=0;//因为置位set的优先级肯定要高啊,因为不管先前add了多少的值在这段区间,如果只要出现了一次的set那么值都是set放的z值
sets[rt]=z;
maxs[rt]=z;
mins[rt]=z;
sum[rt]=(r-l+1)*z;
return ;
}
pushdown(l,r,rt);
mid;
if(x<=m) update_set(lson,x,y,z);
if(y>m) update_set(rson,x,y,z);
maxs[rt]=max(maxs[rt*2],maxs[rt*2+1]);
mins[rt]=min(mins[rt*2],mins[rt*2+1]);
sum[rt]=sum[rt*2]+sum[rt*2+1];
}
node query(int l,int r,int rt,int x,int y)
{
if(x<=l&&y>=r)
{
node tmp;
tmp.maxs=maxs[rt];
tmp.mins=mins[rt];
tmp.sum=sum[rt];
return tmp;
}
pushdown(l,r,rt);
mid;
node t;
if(y<=m) return query(lson,x,y);
else if(x>m) return query(rson,x,y);
else
{
node p,q;
p=query(lson,x,y);
q=query(rson,x,y);
t.sum=p.sum+q.sum;
t.maxs=max(p.maxs,q.maxs);
t.mins=min(p.mins,q.mins);
return t;
}
}
int main()
{
while(scanf("%d%d%d",&r,&c,&m)!=EOF)
{
build(1,r*c,1);
while(m--)
{
scanf("%d%d%d%d%d",&tag,&x1,&y1,&x2,&y2);
if(tag==3)
{
node ans,p;
for(int i=x1;i<=x2;i++)
{
if(i==x1)
ans=query(1,r*c,1,(i-1)*c+y1,(i-1)*c+y2);
else
{
p=query(1,r*c,1,(i-1)*c+y1,(i-1)*c+y2);
ans.sum+=p.sum;
ans.maxs=max(ans.maxs,p.maxs);
ans.mins=min(ans.mins,p.mins);
}
}
printf("%d %d %d\n",ans.sum,ans.mins,ans.maxs);
}
else if(tag==2)
{
scanf("%d",&v);
for(int i=x1;i<=x2;i++)
update_set(1,r*c,1,(i-1)*c+y1,(i-1)*c+y2,v);
}
else if(tag==1)
{
scanf("%d",&v);
for(int i=x1;i<=x2;i++)
update_add(1,r*c,1,(i-1)*c+y1,(i-1)*c+y2,v);
}
}
}
return 0;
}