zoukankan      html  css  js  c++  java
  • UVA 11992 Fast Matrix Operations(线段树:区间修改)

    题目链接 2015-10-30 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3143

    给你一个矩阵,矩阵的每个元素初始值均为0

    进行m次操作,操作共有三种类型,分别用1,2,3表示

    操作一:子矩阵(x1, y1, x2, y2)的所有元素增加v

    操作二:子矩阵(x1, y1, x2, y2)的所有元素设为v

    操作三:查询子矩阵(x1, y1, x2, y2)的元素和,最小值和最大值

    矩阵只有20行,可以每行建一棵线段树(建议直接转为一维)

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #define maxn 3000100
    #define inf 1000000000
    #define LL(x) x<<1
    #define RR(x) x<<1|1
    using namespace std;
    
    typedef long long LL;
    
    //variable define
    
    struct tree
    {
        int l, r;
        int mi, ma, sum;
        int add, set;
    };
    
    tree node[maxn];
    int row, col, m, ans_mi, ans_ma, ans_sum;
    
    //function define
    
    void push_down(int x);
    
    void push_up(int x);
    
    void build_tree(int left, int right, int x);
    
    void query(int left, int right, int x);
    
    void update_set(int left, int right, int x, int val);
    
    void update_add(int left, int right, int x, int val);
    
    int main(void)
    {
        while (scanf("%d %d %d", &row, &col, &m) != EOF)
        {
            build_tree( 1, row*col, 1);
            int op, x1, y1, x2, y2, val;
            while (m--)
            {
                scanf("%d", &op);
                if (op == 1)
                {
                    scanf("%d %d %d %d %d", &x1, &y1, &x2, &y2, &val);
                    for (int i = x1; i <= x2; ++i)
                        update_add( (i-1)*col + y1, (i-1)*col + y2, 1, val);
                }
                else if (op == 2)
                {
                    scanf("%d %d %d %d %d", &x1, &y1, &x2, &y2, &val);
                    for (int i = x1; i <= x2; ++i)
                        update_set( (i-1)*col + y1, (i-1)*col + y2, 1, val);
                }
                else
                {
                    scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
                    ans_sum = 0;
                    ans_ma = -inf;
                    ans_mi = inf;
                    for (int i = x1; i <= x2; ++i)
                        query( (i-1)*col + y1, (i-1)*col + y2, 1);
                    //output
                    printf("%d %d %d\n", ans_sum, ans_mi, ans_ma);
                }
            }
        }
        return 0;
    }
    
    void build_tree(int left, int right, int x)
    {
        node[x].l = left;
        node[x].r = right;
        node[x].ma = node[x].mi = node[x].sum = 0;
        node[x].add = 0;
        node[x].set = -1;
        
        if (left == right)
            return;
        
        int lx = LL(x);
        int rx = RR(x);
        int mid = left + (right - left)/2;
        build_tree(left, mid, lx);
        build_tree(mid + 1, right, rx);
        //push_up(x);
    }
    
    void push_up(int x)
    {
        if (node[x].l >= node[x].r)
            return;
        
        int lx = LL(x);
        int rx = RR(x);
        node[x].ma = max( node[lx].ma, node[rx].ma);
        node[x].mi = min( node[lx].mi, node[rx].mi);
        node[x].sum = node[lx].sum + node[rx].sum;
    }
    
    void push_down(int x)
    {
        if (node[x].l >= node[x].r)
            return;
        int lx = LL(x);
        int rx = RR(x);
        if (node[x].set != -1)
        {
            node[lx].set = node[rx].set = node[x].set;
            node[lx].mi = node[rx].mi = node[x].set;
            node[lx].ma = node[rx].ma = node[x].set;
            node[lx].add = node[rx].add = 0;
            node[lx].sum = (node[lx].r - node[lx].l + 1) * node[x].set;
            node[rx].sum = (node[rx].r - node[rx].l + 1) * node[x].set;
        }
        if (node[x].add > 0)
        {
            LL tmp = node[x].add;
            node[lx].add += tmp;
            node[rx].add += tmp;
            node[lx].ma += tmp;
            node[rx].ma += tmp;
            node[lx].mi += tmp;
            node[rx].mi += tmp;
            node[lx].sum += (tmp * (node[lx].r - node[lx].l + 1));
            node[rx].sum += (tmp * (node[rx].r - node[rx].l + 1));
        }
    }
    
    void update_set(int left, int right, int x, int val)
    {
        if (node[x].l == left && node[x].r == right)
        {
            node[x].set = val;
            node[x].ma = node[x].mi = val;
            node[x].sum = (right - left + 1) * val;
            node[x].add = 0;
            return;
        }
        push_down(x);
        node[x].set = -1;
        node[x].add = 0;
        int lx = LL(x);
        int rx = RR(x);
        int mid = node[x].l + (node[x].r - node[x].l)/2;
        if (right <= mid)
            update_set(left, right, lx, val);
        else if (left > mid)
            update_set(left, right, rx, val);
        else
        {
            update_set(left, mid, lx, val);
            update_set(mid + 1, right, rx, val);
        }
        push_up( x);
    }
    
    void update_add(int left, int right, int x, int val)
    {
        if (node[x].l == left && node[x].r == right)
        {
            node[x].add += val;
            node[x].ma += val;
            node[x].mi += val;
            node[x].sum += (node[x].r - node[x].l + 1) * val;
            return;
        }
        push_down( x);
        node[x].set = -1;
        node[x].add = 0;
        int lx = LL(x);
        int rx = RR(x);
        int mid = node[x].l + (node[x].r - node[x].l)/2;
        
        if (right <= mid)
            update_add(left, right, lx, val);
        else if (left > mid)
            update_add(left, right, rx, val);
        else
        {
            update_add(left, mid, lx, val);
            update_add(mid + 1, right, rx, val);
        }
        push_up(x);
    }
    
    void query(int left, int right, int x)
    {
        if (node[x].l == left && node[x].r == right)
        {
            ans_sum += node[x].sum;
            ans_ma = max( ans_ma, node[x].ma);
            ans_mi = min( ans_mi, node[x].mi);
            return;
        }
        push_down(x);
        node[x].set = -1;
        node[x].add = 0;
        int mid = node[x].l + (node[x].r - node[x].l)/2;
        int lx = LL(x);
        int rx = RR(x);
        if (right <= mid)
            query(left, right, lx);
        else if (left > mid)
            query(left, right, rx);
        else
        {
            query(left, mid, lx);
            query(mid + 1, right, rx);
        }
        push_up(x);
    }
  • 相关阅读:
    C#获取ip地址
    WPF拖动按钮实现(一)
    数据实体层
    在MSN、QQ群、论坛上提问的决窍
    控件开发及组件开发之我见
    数据结构与算法(2) vector概念介绍
    数据结构与算法(1) 数据结构概览
    Android反编译实战(5)
    自己实现CursorAdapter
    自己实现ArrayAdapter
  • 原文地址:https://www.cnblogs.com/chuninsane/p/4923188.html
Copyright © 2011-2022 走看看