zoukankan      html  css  js  c++  java
  • 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
    ", _min, _max);
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Android新手引导库推荐
    windbg 常调用指令
    通过Hook NtOpenProcess 函数实现反调试
    PE文件
    消息机制
    软件调试
    异常(2) --- 编译器对于SEH异常的拓展
    异常(1)
    等待对象
    进程与线程
  • 原文地址:https://www.cnblogs.com/guangheli/p/9845188.html
Copyright © 2011-2022 走看看