https://vjudge.net/problem/UVA-11992
题意:给定一个矩阵,最多20行,最多1e6列。给定m次操作,每次給一个矩形加值或覆盖一个值,或者查询矩形元素和。
思路:《训练指南》的例题。
20行,那就开20个线段树,每个维护一行,同时有setv和addv的标记,那么规定:先执行setv,再执行addv。每次setv修改时,都修改addv为0。注意懒标记的下传和维护即可。

#include<bits/stdc++.h>
using namespace std;
#define maxn (1000000+100)

int r,c,m;
int ql,qr,val,op;
struct SegmentTree{
	int addv[maxn*4],setv[maxn*4],sumv[maxn*4],minv[maxn*4],maxv[maxn*4];
	int _sum,_min,_max;

	void init(){_sum=0;_min=(1<<30);_max=0;}

	void maintain(int o,int l,int r)
	{
		if(setv[o]!=-1)
		{
			sumv[o]=setv[o]*(r-l+1);
			minv[o]=maxv[o]=setv[o];
		}
		else
		{
			sumv[o]=sumv[o*2]+sumv[o*2+1];
			minv[o]=min(minv[o*2],minv[o*2+1]);
			maxv[o]=max(maxv[o*2],maxv[o*2+1]);
		}
		sumv[o]+=addv[o]*(r-l+1);
		minv[o]+=addv[o];
		maxv[o]+=addv[o];
	}

	void pushdown(int o)
	{
		if(setv[o]!=-1)
		{
			setv[o*2]=setv[o*2+1]=setv[o];
			addv[o*2]=addv[o*2+1]=0;
			setv[o]=-1;
		}
		if(addv[o]!=0)
		{
			addv[o*2]+=addv[o];
			addv[o*2+1]+=addv[o];
			addv[o]=0;
		}
	}

	void update(int o,int l,int r)
	{
		if(ql<=l&&qr>=r)
		{
			if(op==2){setv[o]=val;addv[o]=0;}
			else addv[o]+=val;
		}
		else
		{
			int mid=(l+r)/2;
			pushdown(o);
			if(ql<=mid)update(o*2,l,mid);else maintain(o*2,l,mid);
			if(qr>mid)update(o*2+1,mid+1,r);else maintain(o*2+1,mid+1,r);
		}
		maintain(o,l,r);
	}

	void query(int o,int l,int r)
	{
		if(ql<=l&&qr>=r)
		{
			_sum+=sumv[o];	
			_min=min(_min,minv[o]);
			_max=max(_max,maxv[o]);
		}
		else
		{
			int mid=(l+r)/2;
			pushdown(o);
			maintain(o*2,l,mid);maintain(o*2+1,mid+1,r);
			maintain(o,l,r);
			if(ql<=mid)query(o*2,l,mid);
			if(qr>mid)query(o*2+1,mid+1,r);
		}		
	}
};

SegmentTree tree[25];

int main()
{
	//freopen("input.in","r",stdin);
	int r1,r2;
	while(cin>>r>>c>>m)
	{
		for(int i=1;i<=20;i++)tree[i].setv[1]=tree[i].addv[1]=0,tree[i].maintain(1,1,c);
		while(m--)
		{	
			scanf("%d%d%d%d%d",&op,&r1,&ql,&r2,&qr);
			if(op!=3)
			{
				scanf("%d",&val);
				for(int i=r1;i<=r2;i++)tree[i].update(1,1,c);
			}
			else 
			{	
				long long ans1=0;
				int ans2=(1<<30),ans3=0;
				for(int i=r1;i<=r2;i++)
				{
					tree[i].init();
					tree[i].query(1,1,c);
					ans1+=tree[i]._sum;
					ans2=min(ans2,tree[i]._min);
					ans3=max(ans3,tree[i]._max);
				}
				printf("%lld %d %d\n",ans1,ans2,ans3);
			}
		}
	}
	return 0;
}