chuninsane

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);
}

 

posted on 2015-10-30 14:22  chuninsane  阅读(133)  评论(0编辑  收藏  举报

导航