uva 11992 Fast Matrix Operations 线段树模板

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

#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;
}

猜你喜欢

转载自blog.csdn.net/liyong1009s/article/details/82288434