Uva 11992 Fast Matrix Operations (二维线段树)

Fast Matrix Operations

题意: 给定一个r<=20 c<=10^6的全0矩阵

 op1: 子矩阵元素全部增加v

 op2: 子矩阵元素全部变成v

 op3: 查询子矩阵的元素和, 最小值, 最大值


分析: 二维线段树裸题啦~ 这个题对于回复状态非常不错哒, 几乎包含了一般线段树的所有情况

 要注意一下push_down的时候    setv的优先级大于addv    然后setv之后要把addv置0, update的时候也要注意这个


代码: HH版线段树 由于是二维的 我简单封装了一下 这样看起来好看

//
//  Created by TaoSama on 2015-09-14
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e6 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

int r, n, q;
int Sum, Max, Min;

#define root 1, n, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1

struct SegTree {
    int sum[N << 2], maxv[N << 2], minv[N << 2], setv[N << 2], addv[N << 2];

    void push_up(int rt) {
        sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
        maxv[rt] = max(maxv[rt << 1], maxv[rt << 1 | 1]);
        minv[rt] = min(minv[rt << 1], minv[rt << 1 | 1]);
    }
    void push_down(int rt, int m) {
        if(setv[rt]) {
            setv[rt << 1] = setv[rt << 1 | 1] = setv[rt];
            addv[rt << 1] = addv[rt << 1 | 1] = 0;
            sum[rt << 1] = setv[rt] * (m - (m >> 1));
            sum[rt << 1 | 1] = setv[rt] * (m >> 1);
            maxv[rt << 1] = maxv[rt << 1 | 1] = setv[rt];
            minv[rt << 1] = minv[rt << 1 | 1] = setv[rt];
            setv[rt] = 0;
        }
        if(addv[rt]) {
            addv[rt << 1] += addv[rt];
            addv[rt << 1 | 1] += addv[rt];
            sum[rt << 1] += addv[rt] * (m - (m >> 1));
            sum[rt << 1 | 1] += addv[rt] * (m >> 1);
            maxv[rt << 1] += addv[rt];
            maxv[rt << 1 | 1] += addv[rt];
            minv[rt << 1] += addv[rt];
            minv[rt << 1 | 1] += addv[rt];
            addv[rt] = 0;
        }
    }
    void update(int L, int R, int v, int op, int l, int r, int rt) {
        if(L <= l && r <= R) {
            if(op == 2) {
                setv[rt] = v;
                addv[rt] = 0;
                sum[rt] = (r - l + 1) * v;
                maxv[rt] = minv[rt] = v;
            } else {
                addv[rt] += v;
                sum[rt] += (r - l + 1) * v;
                maxv[rt] += v, minv[rt] += v;
            }
            return;
        }
        int m = l + r >> 1;
        push_down(rt, r - l + 1);
        if(L <= m) update(L, R, v, op, lson);
        if(R > m) update(L, R, v, op, rson);
        push_up(rt);
    }
    void query(int L, int R, int l, int r, int rt) {
        if(L <= l && r <= R) {
            Sum += sum[rt];
            Min = min(Min, minv[rt]);
            Max = max(Max, maxv[rt]);
            return;
        }
        int m = l + r >> 1;
        push_down(rt, r - l + 1);
        if(L <= m) query(L, R, lson);
        if(R > m) query(L, R, rson);
    }
} T[21];

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(scanf("%d%d%d", &r, &n, &q) == 3) {
        memset(T, 0, sizeof T);
        while(q--) {
            int op, x1, x2, y1, y2, v;
            scanf("%d%d%d%d%d", &op, &x1, &y1, &x2, &y2);
            if(op <= 2) {
                scanf("%d", &v);
                for(int i = x1; i <= x2; ++i)
                    T[i].update(y1, y2, v, op, root);
            } else {
                Sum = 0; Max = -INF; Min = INF;
                for(int i = x1; i <= x2; ++i)
                    T[i].query(y1, y2, root);
                printf("%d %d %d\n", Sum, Min, Max);
            }
        }
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值