UVA11992 - Fast Matrix Operations(段树部分的变化)

UVA11992 - Fast Matrix Operations(线段树区间改动)

题目链接

题目大意:给你个r*c的矩阵,初始化为0。

然后给你三种操作:

1 x1, y1, x2, y2, v 把由x1,y1, x2, y2构成的子矩阵里的每一个元素都加上v。

2 x1, y1, x2, y2, v 把这个子矩阵的每一个元素都改动为v。

3 x1, y1, x2, y2 查询这个子矩阵的元素之和,和这些元素的最大值和最小值。

解题思路:由于矩阵的行最多20行,所以能够将这个矩阵的元素构建一棵线段树,每一个节点都有三个附加信息:sum,Max_num, Min_num.然后改动查询的时候就每行每行的来做。注意:每次set的时候都要将这个节点的add清理掉。由于add已经是不须要的了。

然后每次的pushdown都要先处理set再处理add。pushdown处理的是这个节点的子节点。然后通过pushup就能够更新这个节点的附加信息。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

#define lson(x) ((x)<<1)
#define rson(x) (((x)<<1) + 1)

const int N = 1e6 + 5;
const int INF = 0x3f3f3f3f;

struct Item {

    int sum, Max_num, Min_num;

    Item (int sum = 0, int Max_num = -INF, int Min_num = INF) {
        this->set(sum, Max_num, Min_num);
    }

    void set (int sum, int Max_num, int Min_num) {
        this->sum = sum;
        this->Max_num = Max_num;
        this->Min_num  = Min_num;
    }
};

struct Node {

    Item v;
    int l, r;
    int addv, setv;

    void set (int l, int r, int addv = 0, int setv = -1) {
        this->l = l;
        this->r = r;
        this->addv = addv;
        this->setv = setv;
    }

}node[4 * N];

Item get_item (Item a, Item b) {

    return Item(a.sum + b.sum, max(a.Max_num, b.Max_num), min(a.Min_num, b.Min_num));
}

void Node_add(int u, int addv) {

    node[u].addv += addv;
    node[u].v.sum += addv * (node[u].r - node[u].l + 1);
    node[u].v.Max_num += addv;
    node[u].v.Min_num += addv;
}

void Node_set(int u, int setv) {

    node[u].setv = setv;
    node[u].addv = 0;
    node[u].v.sum = setv * (node[u].r - node[u].l + 1);
    node[u].v.Max_num = node[u].v.Min_num = setv;
}

void pushup (int u) {

    node[u].set(node[lson(u)].l, node[rson(u)].r);
    node[u].v = get_item(node[lson(u)].v, node[rson(u)].v);
}

void pushdown(int u) {

    if (node[u].setv >= 0) {
        Node_set(lson(u), node[u].setv);
        Node_set(rson(u), node[u].setv);
        node[u].setv = -1;
    }

    if (node[u].addv) {
        Node_add(lson(u), node[u].addv);
        Node_add(rson(u), node[u].addv);
        node[u].addv = 0;
    }
}

void Build (int u, int l, int r) {

    if (l == r) {
        node[u].set(l, r);
        node[u].v.set(0, 0, 0);

    } else {

        int m = (l + r) / 2;
        Build(lson(u), l, m);
        Build(rson(u), m + 1, r);
        pushup(u);
    }
}

void Add (int u, int l, int r, int addv) {

    if (node[u].l >= l && node[u].r <= r)
        Node_add(u, addv);
    else {

        pushdown(u);
        int m = (node[u].l + node[u].r) / 2;
        if (l <= m)
            Add (lson(u), l, r, addv);
        if (r > m)
            Add (rson(u), l, r, addv);
        pushup(u);
    }
}

void Set (int u, int l, int r, int setv) {

    if (node[u].l >= l && node[u].r <= r)
        Node_set(u, setv);
    else {

        pushdown(u);
        int m = (node[u].l + node[u].r) / 2;
        if (l <= m)
            Set (lson(u), l, r, setv);
        if (r > m)
            Set (rson(u), l, r, setv);
        pushup(u);
    }
}

Item Query (int u, int l, int r) {

    if (node[u].l >= l && node[u].r <= r)
        return node[u].v;
    else {

        Item ans;

        pushdown(u);
        int m = (node[u].l + node[u].r) / 2;
        if (l <= m)
            ans = get_item (ans, Query(lson(u), l, r));
        if (r > m)
            ans = get_item (ans, Query(rson(u), l, r));
        pushup(u);

        return ans;
    }
}

int main () {

    int r, c, m;
    int type;
    int x1, y1, x2, y2, v;

    while (scanf ("%d%d%d", &r, &c, &m) != EOF) {

        Build(1, 1, r * c);

        while (m--) {

            scanf ("%d", &type);

            if (type == 1) {

                scanf ("%d%d%d%d%d", &x1, &y1, &x2, &y2, &v);

                for (int i = x1 - 1; i < x2; i++)
                    Add(1, i * c + y1, i * c + y2, v);
            } else if (type == 2) {

                scanf ("%d%d%d%d%d", &x1, &y1, &x2, &y2, &v);
                for (int i = x1 - 1; i < x2; i++)
                    Set(1, i * c + y1, i * c + y2, v);
            } else {

                scanf ("%d%d%d%d", &x1, &y1, &x2, &y2);

                Item ans;
                for (int i = x1 - 1; i < x2; i++)
                    ans = get_item(ans, Query(1, i * c + y1, i * c + y2));
                printf ("%d %d %d\n", ans.sum, ans.Min_num, ans.Max_num);
            }
        }
    }
    return 0;
}

版权声明:本文博主原创文章,博客,未经同意不得转载。

时间: 2024-08-25 00:36:26

UVA11992 - Fast Matrix Operations(段树部分的变化)的相关文章

UVA11992 - Fast Matrix Operations ( 线段树 + 区间修改 + 好题 )

UVA11992 - Fast Matrix Operations ( 线段树 + 区间修改 + 好题 ) 这是大白书上的例题,一直放着没有去A掉,这是一道线段树区间修改的好题. 线段树中需要维护三个域 ,max, min, sum,也就是区间最大值,最小值,区间和 题目大意: r 行 c 列 的全0矩阵,支持三个操作 1 x1 y1 x2 y2 v 子矩阵(x1,y1,x2,y2)的所有元素增加v 2 x1 y1 x2 y2 v 子矩阵(x1,y1,x2,y2)的所有元素设为v 3 x1 y1

UVA11992 - Fast Matrix Operations(线段树区间修改)

题目链接 题目大意:给你个r*c的矩阵,初始化为0. 然后给你三种操作: 1 x1, y1, x2, y2, v 把由x1,y1, x2, y2构成的子矩阵里的每个元素都加上v. 2 x1, y1, x2, y2, v 把这个子矩阵的每个元素都修改为v. 3 x1, y1, x2, y2 查询这个子矩阵的元素之和,和这些元素的最大值和最小值. 解题思路:因为矩阵的行最多20行,所以可以将这个矩阵的元素构建一棵线段树,每个节点都有三个附加信息:sum,Max_num, Min_num.然后修改查询

UVA11992:Fast Matrix Operations(线段树)

题意: 有一个初始状态全为0的矩阵,一共有三个操作 1 x1 y1 x2 y2 v:子矩阵(x1,y1,x2,y2)所有元素增加v 2 x1 y1 x2 y2 v:子矩阵(x1,y1,x2,y2)所有元素设为v 3 x1 y1 x2 y2 v:查询子矩阵(x1,y1,x2,y2)的元素和,最大值和最小值 思路: 因为总元素葛素不超过10^6,而且更新是对于连续的行进行更新,所以我们可以把矩阵转化为一个一元组,通过下一行拼接在上一行的末尾,那么在更新与查询的时候只要对相应的区间进行操作即可 #in

UVA 11992(Fast Matrix Operations-线段树区间加&amp;改)[Template:SegmentTree]

Fast Matrix Operations There is a matrix containing at most 106 elements divided into r rows and c columns. Each element has a location (x,y) where 1<=x<=r,1<=y<=c. Initially, all the elements are zero. You need to handle four kinds of operati

UVa 11992 Fast Matrix Operations (线段树)

Fast Matrix Operations Description There is a matrix containing at most 106 elements divided into r rows and c columns. Each element has a location (x, y) where 1 ≤ x ≤ r, 1 ≤ y ≤ c. Initially, all the elements are zero. You need to handle four kinds

[uva11992]Fast Matrix Operations(多延迟标记,二维线段树,区间更新)

题目链接:https://vjudge.net/problem/UVA-11992 题意:n*m的矩阵,每次对一个子矩阵操作,有三种操作:加x,设置为x,查询.查询返回子矩阵和.最小值.最大值 n很小(<=20),所以可以开20棵线段树,每次操作按行更新. 特别小心put和add两个延迟标记,坑老惨了. put初始化-1最简单的坑,略过. build的时候要每一个节点都要clear,不能只clear叶子.因为会有直接差没操作的子矩阵(因为初始化都是0). 数组开大... add的话,什么都不用管

uva11992 Fast Matrix Operations

题意:r*c的矩阵上,初始全部为0,有3中操作,子矩阵全部增加v,子矩阵值修改为v,查询子矩阵的最大值,最小值,和 分析:因为有setv和addv两种操作,那么需要开两个数组记录这个值,每次需要用到一个节点的儿子,那么就把该节点的setv,addv信息推过去,并且setv的优先级要高于addv,不过这样的后果就是,慢 不过这样写思维难度和编程难度降低了,一般并不会发生线段树不够快的情况 1 #include<iostream> 2 #include<cstring> 3 #incl

Fast Matrix Operations

uva11992:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3143 题意:给你n*m的矩阵初始化的时候矩阵里面的元素全部是0,对于这个矩阵有3中操作. 1 x1 y1 x2 y2 v   把(x1 y1 x2 y2)子矩阵 里面的元素全部加上v 2 x1 y1 x2 y2 v   把(x1 y1 x2 y2)子矩阵 里面的元素全部置成

UVA 11992 - Fast Matrix Operations

Fast Matrix Operations There is a matrix containing at most 106 elements divided into r rows and c columns. Each element has a location (x,y) where 1<=x<=r,1<=y<=c. Initially, all the elements are zero. You need to handle four kinds of operati