uva11992 Fast Martix Operations 线段树区间set+区间add

版权声明:若转载请附上原博客链接,谢谢! https://blog.csdn.net/Link_Ray/article/details/86499398

题意

有一个r行c列的全0矩阵,支持以下3种操作,如表所示。

操作 备注
1 x1 y1 x2 y2 v 子矩阵(x1,y1,2,y2)的所有元素增加v(v>0)
2 x1 y1 x2 y2 v 子矩阵(x1,y1,x2,y2)的所有元素设为v(v>0)
3 x1 y1 x2 y2 查询子矩阵(x1,y1,x2,y2)的元素和、最小值和最大值

子矩阵(x1,y1,x2,y2)是指满足 x 1 x x 2 , y 1 y y 2 x_1\leq x \leq x_2, y_1 \leq y \leq y_2 的所有元素(x,y)。所有元素和不超过 1 0 9 10^9 。矩阵不超过20行,元素个数不超过 1 0 6 10^6

题解

由于元素个数不超过20个,所以可以把二维矩阵压成一维。在一维结构上进行线段树的操作。这里主要有set和add操作,要注意的是pushdown的时候set操作要在add之前。set操作之后要把add的标记清零。

具体代码

/*************************************************************************
    > File Name: Uva11992.cpp
    > Author: KyrieL
    > Mail: [email protected]
    > Created Time: 二  1/15 14:15:02 2019
 ************************************************************************/

#include <bits/stdc++.h>
using namespace std;

#define lson l,mid,rt<<1
#define rson mid+1, r, rt<<1|1
const int maxn = 1e6+100;
int setv[maxn<<2], addv[maxn<<2],r,c,m, sumv[maxn<<2], minv[maxn<<2],maxv[maxn<<2];
void pushdown(int rt,int l,int r) {
    int mid = (l+r)>>1;
    if(setv[rt] > 0) {
        int val = setv[rt];
        minv[rt<<1] = maxv[rt<<1] = val;
        sumv[rt<<1] = val*(mid-l+1); 
        minv[rt<<1|1] = maxv[rt<<1|1] = val;
        sumv[rt<<1|1] = val*(r-mid);
        setv[rt<<1|1] = setv[rt<<1] = val; 
        addv[rt<<1|1] = addv[rt<<1] = 0;
        setv[rt] = 0;
    }
    if(addv[rt] > 0) {
        minv[rt<<1] += addv[rt]; minv[rt<<1|1] += addv[rt];
        maxv[rt<<1] += addv[rt]; maxv[rt<<1|1] += addv[rt];
        sumv[rt<<1] += addv[rt]*(mid-l+1); sumv[rt<<1|1] += addv[rt]*(r-mid);
        addv[rt<<1] += addv[rt];
        addv[rt<<1|1] += addv[rt];
        addv[rt] = 0;
    }
}
void pushup(int rt) {
    minv[rt] = min(minv[rt<<1], minv[rt<<1|1]);
    maxv[rt] = max(maxv[rt<<1], maxv[rt<<1|1]);
    sumv[rt] = sumv[rt<<1]+sumv[rt<<1|1];
}
void updateAdd(int L,int R,int v,int l,int r,int rt) {
    if(L > r || R < l) {
        return;
    }
    if(L <= l && r <= R) {
        int add = (r-l+1)*v;
        sumv[rt] += add;
        addv[rt] += v;
        minv[rt] += v;
        maxv[rt] += v;
        return;
    }
    pushdown(rt,l,r);
    int mid = (l+r)>>1;
    updateAdd(L,R,v,lson);
    updateAdd(L,R,v,rson);
    pushup(rt);
}

void updateSet(int L,int R,int v,int l,int r,int rt) {
    if(L > r || R < l) {
        return ;
    }
    if(L <= l && r <= R) {
        int val = (r-l+1)*v;
        sumv[rt] = val;
        minv[rt] = maxv[rt] = v;
        addv[rt] = 0;
        setv[rt] = v;
        return;
    }
    pushdown(rt,l,r);
    int mid = (l+r) >> 1;
    updateSet(L,R,v,lson);
    updateSet(L,R,v,rson);
    pushup(rt);
}
int _sum, _min, _max;
void query(int L,int R,int l,int r,int rt) {
    if(L > r || R < l) {
        return;
    }
    if(L <= l && r <= R) {
        _sum += sumv[rt];
        _min = min(_min, minv[rt]);
        _max = max(_max, maxv[rt]);
        return;
    }
    pushdown(rt,l,r);
    int mid = (l+r)>>1;
    query(L,R,lson);
    query(L,R,rson);
    pushup(rt);
}
int main() {
    // freopen("in.txt","r",stdin);
    while(scanf("%d%d%d",&r,&c,&m)==3) {
        memset(sumv, 0, sizeof sumv);
        memset(minv, 0,sizeof minv);
        memset(maxv, 0, sizeof maxv);
        memset(addv,0,sizeof addv);
        memset(setv,0,sizeof setv);
        int op,x1,x2,y1,y2,v;
        int n = r*c;
        // cout << n << endl;
        for(int i = 0; i < m; ++i) {
            scanf("%d", &op);
            if(op == 1) {
                scanf("%d%d%d%d", &x1,&y1,&x2,&y2);
                scanf("%d", &v);
                // cout << x1 <<" " << x2 << endl;
                for(int j = x1; j <= x2; ++j) {
                    int l = (j-1)*c+y1;
                    int r = (j-1)*c+y2;
                    // cout << l << " " << r << endl;
                    updateAdd(l,r,v,1,n,1);
                }
            }
            else if(op == 2) {
                scanf("%d%d%d%d", &x1,&y1,&x2,&y2);
                scanf("%d", &v);
                for(int j = x1; j <= x2; ++j) {
                    int l = (j-1)*c+y1;
                    int r = (j-1)*c+y2;
                    updateSet(l,r,v,1,n,1);
                }
            }
            else {
                scanf("%d%d%d%d", &x1,&y1,&x2,&y2);
                _sum = 0; _min = 1e9; _max = 0;
                for(int j = x1; j <= x2; ++j) {
                    int l = (j-1)*c+y1;
                    int r = (j-1)*c+y2;
                    query(l,r,1,n,1);
                    // cout << _sum << endl;
                }
                
                printf("%d %d %d\n", _sum, _min, _max);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Link_Ray/article/details/86499398