uva 11992 Fast Matrix Operations (线段树区间更新)

题意:

给你一个矩阵,然后有3种操作:
1 x1 y1 x2 y2 val 是将矩阵x1 y1 x2 y2的区间内的值全部增加val
2 x1 y1 x2 y2 val 是将矩阵x1 y1 x2 y2的区间内的值全部设置为val
3 x1 y1 x2 y2 求出 x1 y1 x2 y2的区间内的和,最大值,最小值。

解析:

这个题是一道线段树题,要求进行区间修改设置以及求和。
由于r <= 20,r*c <= 1e6,所以我们可以将矩阵展开成一维,每次询问进行(x2-x1)次查询操作即可。这样就转换成了线段树问题。
我们做addv标记加val操作,用setv标记变val操作;若遇到setv,我们需要清空addv,反之则不需要。若在操作的时候setv和addv都存在,那么先执行setv操作,之后执行addv操作。

AC代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ls o*2
#define rs o*2+1
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = (1e6+5)*4;
int sumv[N], minv[N], maxv[N];
int addv[N], setv[N];
int ql, qr, val;
int x1, y1, x2, y2;
int _sum, _max, _min;

inline void maintain(int o) {
    sumv[o] = sumv[ls] + sumv[rs];
    minv[o] = min(minv[ls], minv[rs]);
    maxv[o] = max(maxv[ls], maxv[rs]);
}

void build(int o, int L, int R) {
    if(L == R) {
        sumv[o] = minv[o] = maxv[o] = 0;
        addv[o] = setv[o] = 0;  
        return ;
    }
    int M = (L+R)/2;
    build(ls, L, M);
    build(rs, M+1, R);
    maintain(o);
}

void pushdown(int o, int L, int R) {
    int M = (L+R)/2;
    if(setv[o]) {
        setv[ls] = setv[rs] = setv[o]; 
        addv[ls] = addv[rs] = 0;
        sumv[ls] = (M-L+1)*setv[o], sumv[rs] = (R-M)*setv[o];
        minv[ls] = minv[rs] = setv[o];
        maxv[ls] = maxv[rs] = setv[o];
        setv[o] = 0;
    }
    if(addv[o]) {
        addv[ls] += addv[o], addv[rs] += addv[o];
        sumv[ls] += (M-L+1) * addv[o], sumv[rs] += (R-M) * addv[o];
        minv[ls] += addv[o], minv[rs] += addv[o];
        maxv[ls] += addv[o], maxv[rs] += addv[o];
        addv[o] = 0;
    }
}

void add(int o, int L, int R) {
    if(ql <= L && R <= qr) {
        addv[o] += val;
        sumv[o] += (R-L+1) * val;
        minv[o] += val;
        maxv[o] += val;
        return ;
    }
    pushdown(o, L, R);
    int M = (L+R)/2;
    if(ql <= M) add(ls, L, M);
    if(qr > M) add(rs, M+1, R);
    maintain(o);
}

void set(int o, int L, int R) {
    if(ql <= L && R <= qr) {
        setv[o] = val;
        sumv[o] = (R-L+1) * val;
        minv[o] = maxv[o] = val;
        addv[o] = 0;
        return ;
    }
    pushdown(o, L, R);
    int M = (L+R)/2;
    if(ql <= M) set(ls, L, M);
    if(qr > M) set(rs, M+1, R);
    maintain(o);
}

void query(int o, int L, int R) {
    if(ql <= L && R <= qr) {
        _sum += sumv[o];
        _min = min(_min, minv[o]);
        _max = max(_max, maxv[o]);
        return ;
    }
    pushdown(o, L, R);
    int M = (L+R)/2;
    if(ql <= M) query(ls, L, M);
    if(qr > M) query(rs, M+1, R);
}

int main() {
    int r, c, q, ch;
    int n;
    while(scanf("%d%d%d", &r, &c, &q) != EOF) {
        n = r*c;
        build(1, 1, n);
        while(q--) {
            scanf("%d%d%d%d%d", &ch, &x1, &y1, &x2, &y2);
            switch(ch) {
                case 1:
                    scanf("%d", &val);
                    for(int i = x1; i <= x2; i++) {
                        ql = (i-1)*c + y1;
                        qr = (i-1)*c + y2;
                        add(1, 1, n);
                    }
                    break;
                case 2:
                    scanf("%d", &val);
                    for(int i = x1; i <= x2; i++) {
                        ql = (i-1)*c + y1;
                        qr = (i-1)*c + y2;
                        set(1, 1, n);
                    }
                    break;
                case 3:
                    _sum = 0, _min = INF, _max = -INF;
                    for(int i = x1; i <= x2; i++) {
                        ql = (i-1)*c + y1;
                        qr = (i-1)*c + y2;
                        query(1, 1, n);
                    }
                    printf("%d %d %d\n", _sum, _min, _max);
                    break;
            } 
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值