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-10-06 11:59:09

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(线段树)

题意: 有一个初始状态全为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

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行,所以能够将这个矩阵的元素构建一

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

HDU - 1698 Just a Hook (线段树区间修改)

Description In the game of DotA, Pudge's meat hook is actually the most horrible thing for most of the heroes. The hook is made up of several consecutive metallic sticks which are of the same length. Now Pudge wants to do some operations on the hook.

hdu 4902 Nice boat(线段树区间修改,输出最终序列)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 Problem Description There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his peopl

杭电 1698 Just a Hook(线段树区间修改)

http://acm.hdu.edu.cn/showproblem.php?pid=1698 Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 17322    Accepted Submission(s): 8640 Problem Description In the game of DotA, Pudge's

hdu1698 Just a Hook(线段树+区间修改+区间查询+模板)

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 54923    Accepted Submission(s): 25566 Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of

poj 2777 Count Color(线段树区间修改)

题目链接:http://poj.org/problem?id=2777 题目意思:就是问你在询问的区间里有几种不同的颜色 思路:这题和一般的区间修改差不多,但是唯一不同的就是我们要怎么计算有种颜色,所以这时候我们就需要把延时标记赋予不同的意义,当某段区间有多种颜色时就赋值为-1,当为一种颜色时就把它赋值为这个颜色的号数.这儿我们要怎么统计询问区间不同的颜色数叻,为了不重复计算同一种颜色,那么我们就需要用一个数组来标记计算过的颜色,当我们下次遇到时就不需要再次计算了.... 代码核心处就在计数那儿