Fast Matrix Operations

题意:

二维的区间增、改,求区间最值、和值。

分析:

把二维化为一维,注意懒惰标记。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <cctype>
#include <complex>
#include <cassert>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
#define lson(x) ((x<<1))
#define rson(x) ((x<<1)|1)
#define INF 0x3f3f3f3f
const int N = 1000005;
int r, c, m;
struct Node {
    int l, r;
    int sum, Max, Min, sumv, setv;
} node[4 * N];
void pushup(int x) {
    node[x].sum = node[lson(x)].sum + node[rson(x)].sum;
    node[x].Max = max(node[lson(x)].Max, node[rson(x)].Max);
    node[x].Min = min(node[lson(x)].Min, node[rson(x)].Min);
}

void pushdown(int x) {
    if (node[x].setv) {
    node[lson(x)].sumv = node[rson(x)].sumv = 0;
    node[lson(x)].setv = node[rson(x)].setv = node[x].setv;
    node[lson(x)].sum = (node[lson(x)].r - node[lson(x)].l + 1) * node[x].setv;
    node[rson(x)].sum = (node[rson(x)].r - node[rson(x)].l + 1) * node[x].setv;
    node[lson(x)].Max = node[lson(x)].Min = node[x].setv;
    node[rson(x)].Max = node[rson(x)].Min = node[x].setv;
    node[x].setv = 0;
    }
    if (node[x].sumv) {
    node[lson(x)].sumv += node[x].sumv;
    node[rson(x)].sumv += node[x].sumv;
    node[lson(x)].sum += (node[lson(x)].r - node[lson(x)].l + 1) * node[x].sumv;
    node[rson(x)].sum += (node[rson(x)].r - node[rson(x)].l + 1) * node[x].sumv;
    node[lson(x)].Max += node[x].sumv;
    node[lson(x)].Min += node[x].sumv;
    node[rson(x)].Max += node[x].sumv;
    node[rson(x)].Min += node[x].sumv;
    node[x].sumv = 0;
    }
}

void build(int l, int r, int x) {
    node[x].l = l; node[x].r = r;
    if (l == r) {
    node[x].sum = node[x].Max = node[x].Min = node[x].sumv = node[x].setv = 0;
    return;
    }
    int mid = (l + r) / 2;
    build(l, mid, lson(x));
    build(mid + 1, r, rson(x));
    pushup(x);
}

void update_add(int l, int r, int v, int x) {
    if (node[x].l >= l && node[x].r <= r) {
    node[x].sumv += v;
    node[x].sum += (node[x].r - node[x].l + 1) * v;
    node[x].Max += v;
    node[x].Min += v;
    return;
    }
    pushdown(x);
    int mid = (node[x].l + node[x].r) / 2;
    if (l <= mid) update_add(l, r, v, lson(x));
    if (r > mid) update_add(l, r, v, rson(x));
    pushup(x);
}

void update_set(int l, int r, int v, int x) {
    if (node[x].l >= l && node[x].r <= r) {
    node[x].setv = v;
    node[x].sum = (node[x].r - node[x].l + 1) * v;
    node[x].Max = node[x].Min = v;
    node[x].sumv = 0;
    return;
    }
    pushdown(x);
    int mid = (node[x].l + node[x].r) / 2;
    if (l <= mid) update_set(l, r, v, lson(x));
    if (r > mid) update_set(l, r, v, rson(x));
    pushup(x);
}

Node query(int l, int r, int x) {
    Node ans; ans.sum = 0; ans.Max = 0; ans.Min = INF;
    if (node[x].l >= l && node[x].r <= r) {
    ans.sum = node[x].sum;
    ans.Max = node[x].Max;
    ans.Min = node[x].Min;
    return ans;
    }
    pushdown(x);
    int mid = (node[x].l + node[x].r) / 2;
    if (l <= mid) {
    Node tmp = query(l, r, lson(x));
    ans.sum += tmp.sum;
    ans.Max = max(ans.Max, tmp.Max);
    ans.Min = min(ans.Min, tmp.Min);
    }
    if (r > mid) {
    Node tmp = query(l, r, rson(x));
    ans.sum += tmp.sum;
    ans.Max = max(ans.Max, tmp.Max);
    ans.Min = min(ans.Min, tmp.Min);
    }
    return ans;
}

int main() {
    while (~scanf("%d%d%d", &r, &c, &m)) {
    build(1, r * c, 1);
    int q, x1, y1, x2, y2, v;
    while (m--) {
        scanf("%d", &q);
        if (q == 3) {
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        int sum = 0, Max = 0, Min = INF;
        for (int i = x1; i <= x2; i++) {
            Node ans = query((i-1)* c + y1, (i-1) * c + y2, 1);
            sum += ans.sum;
            Max = max(Max, ans.Max);
            Min = min(Min, ans.Min);
        }
        printf("%d %d %d\n", sum, Min, Max);
        }
        else {
        scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &v);
        for (int i = x1; i <= x2; i++) {
            if (q == 1) update_add((i-1) * c + y1, (i-1) * c + y2, v, 1);
            else update_set((i-1) * c + y1, (i-1) * c + y2, v, 1);
        }
        }
    }
    }
    return 0;
}

 

posted on 2015-10-25 22:24  积跬步、至千里  阅读(156)  评论(0编辑  收藏  举报

导航