uva 11992 Fast Matrix Operations 线段树模板

注意 setsetaddvaddv 标记的下传。
我们可以控制懒惰标记的优先级。
由于 setset 操作的优先级高于 addadd 操作,当下传 setset 操作时可直接强制清空 addaddlazylazy
实际上,当一个节点同时存在 setsetaddadd 标记时,一定是先有的 setset 再被 addadd,因为如果反之,该节点上的 addadd标记会被清空。

#include<cstdio>                //Fast Matrix Operations
#include<algorithm>                        
#include<cstring>                                
using namespace std;
const int maxn = 200000 + 2;
typedef long long ll;
ll sumv[maxn * 2+1][21];
int minv[maxn * 2+1][21], maxv[maxn * 2+1][21];
int lazy[maxn * 2+1][21], set[maxn * 2+1][21];
int chk;
int _min, _max;
void init(){
	memset(sumv, 0, sizeof(sumv));
	memset(minv, 0, sizeof(minv));
	memset(maxv, 0, sizeof(maxv));
	memset(lazy, 0, sizeof(lazy));
	memset(set, 0, sizeof(set));
}                            
void down(int L,int R,int o,int id){
	int mid = (L + R) / 2;
	if (set[o][id]) {
	    int k=set[o][id];
		set[o * 2][id] = set[o * 2 + 1][id] = k;
		sumv[o * 2][id] = (mid - L + 1)*k, sumv[o * 2 + 1][id] = (R - mid)*k;       //更新sum
		minv[o * 2][id] = maxv[o * 2][id] = minv[o * 2 + 1][id] = maxv[o * 2 + 1][id] = k;   //更新minv,maxv
		lazy[o * 2][id] = lazy[o * 2 + 1][id] = 0;
		set[o][id] = 0;
	}
	if (lazy[o][id]){
		int k = lazy[o][id];
		lazy[o * 2][id] += k, lazy[o * 2 + 1][id] += k;
		sumv[o * 2][id] += (mid - L + 1)*k, sumv[o * 2 + 1][id] += (R - mid)*k;
		minv[o * 2][id] += k, maxv[o * 2][id] += k, minv[o * 2 + 1][id] += k, maxv[o * 2 + 1][id] += k;
		lazy[o][id] = 0;
	}
}
void update(int l, int r,int k, int o, int id, int L, int R){
	if (l <= L&&r >= R){
		if (chk == 1) 
		{
			lazy[o][id] += k;
			sumv[o][id] += (R - L + 1)*k;
			minv[o][id] += k, maxv[o][id] += k;
		}
		if (chk == 2) {
			lazy[o][id] = 0;
			sumv[o][id] = (R - L + 1)*k;
			minv[o][id] = maxv[o][id] = k;
			set[o][id] = k;
		}
	}
	else{
		int mid = (L + R) / 2;
		down(L,R,o,id);
		if (l <= mid)update(l, r, k, o * 2, id, L, mid);
		if (r > mid)update(l, r, k, o * 2 + 1, id, mid + 1, R);
		minv[o][id] = min(minv[o * 2][id], minv[o * 2 + 1][id]);
		maxv[o][id] = max(maxv[o * 2][id], maxv[o * 2 + 1][id]);
		sumv[o][id] = sumv[o * 2][id] + sumv[o * 2 + 1][id];
	}
}
ll query(int l, int r, int o, int id, int L, int R){
	if (l <= L&&r >= R) {              //包含
		_min = min(minv[o][id], _min);
		_max = max(maxv[o][id], _max);
		return sumv[o][id];
	}
	else
	{
		int mid = (L + R) / 2;
		ll a = 0;
		down(L,R,o,id);
		if (l <= mid)a += query(l, r, o * 2, id, L, mid);
		if (r > mid)a += query(l, r, o * 2 + 1, id, mid + 1, R);
		maxv[o][id] = max(maxv[o * 2][id], maxv[o*2+1][id]);
		minv[o][id] = min(minv[o * 2][id],minv[o * 2 + 1][id]);
		sumv[o][id] = sumv[o * 2][id] + sumv[o * 2 + 1][id];
		return a;
	}
}
int main(){
	int r, c, m;
	while (scanf("%d", &r) != EOF)
	{
		scanf("%d%d",&c, &m);
		init();
		for (int i = 1; i <= m; ++i)
		{
			scanf("%d", &chk);
			int x1, y1, x2, y2, v;
			scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
			if (chk<3) 
			{
				scanf("%d", &v);
				for (int j = x1; j <= x2; ++j) update(y1, y2, v, 1, j, 1, c);
			}
			if (chk == 3) 
			{
				_min = 10000000 + 123, _max = -12345;
				ll p=0;
				for (int j = x1; j <= x2; ++j)
					p += query(y1, y2, 1, j, 1, c);
				printf("%lld ", p);
				printf("%d %d\n", _min, _max);
			}
		}
	}
	return 0;
}
posted @ 2018-09-01 16:36  EM-LGH  阅读(118)  评论(0编辑  收藏  举报