UVA 11192 Fast Matrix Operations

UVA_11192

    如果是在一维的序列上进行这些操作的话,那么线段树就可以了。不过现在题目将这些操作拓展到了二维,回想线段树的本质是二分线段,那么对于一个二维的矩阵,拓展一下就应当是四分矩阵了。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXD 1000010
#define INF 0x3f3f3f3f
int N, M, P, node;
struct SegTree
{
    int x1, y1, x2, y2, sum, min, max, add, to, son[4], area;    
    void pushdown(); void update();
    void init()
    {
        sum = add = to = 0;
        son[0] = son[1] = son[2] = son[3] = 0;
        min = INF, max = -INF;
    }
}st[4 * MAXD];
inline void To(int cur, int v)
{
    if(cur)
    {
        st[cur].to = v, st[cur].add = 0;
        st[cur].min = st[cur].max = v, st[cur].sum = v * st[cur].area;
    }
}
inline void Add(int cur, int v)
{
    if(cur)
    {
        st[cur].add += v;
        st[cur].min += v, st[cur].max += v, st[cur].sum += v * st[cur].area;    
    }    
}
inline void SegTree::pushdown()
{
    if(to)
    {
        for(int i = 0; i < 4; i ++) To(son[i], to);
        to = 0;
    }
    if(add)
    {
        for(int i = 0; i < 4; i ++) Add(son[i], add);
        add = 0;    
    }
}
inline void SegTree::update()
{
    min = INF, max = -INF, sum = 0;
    for(int i = 0; i < 4; i ++)
    {
        sum += st[son[i]].sum;
        min = std::min(min, st[son[i]].min);
        max = std::max(max, st[son[i]].max);
    }
}
void build(int cur, int x1, int x2, int y1, int y2)
{
    int midx = x1 + x2 >> 1, midy = y1 + y2 >> 1;
    st[cur].init(), st[cur].sum = st[cur].min = st[cur].max = 0;
    st[cur].x1 = x1, st[cur].x2 = x2, st[cur].y1 = y1, st[cur].y2 = y2, st[cur].area = (x2 - x1 + 1) * (y2 - y1 + 1);
    if(x1 == x2 && y1 == y2) return ;
    st[cur].son[0] = ++ node, build(node, x1, midx, y1, midy);
    if(midx < x2)
        st[cur].son[1] = ++ node, build(node, midx + 1, x2, y1, midy);
    if(midx < x2 && midy < y2)
        st[cur].son[2] = ++ node, build(node, midx + 1, x2, midy + 1, y2);
    if(midy < y2)
        st[cur].son[3] = ++ node, build(node, x1, midx, midy + 1, y2);
    st[cur].update();
}
void init()
{
    st[0].init(), node = 1;
    build(1, 1, N, 1, M);
}
inline int inside(int k, int x1, int x2, int y1, int y2)
{
    return st[k].x1 >= x1 && st[k].x2 <= x2 && st[k].y1 >= y1 && st[k].y2 <= y2;
}
inline int inter(int k, int x1, int x2, int y1, int y2)
{
    if(st[k].x2 < x1 || st[k].x1 > x2 || st[k].y2 < y1 || st[k].y1 > y2) return 0;
    return 1;
}
void refresh(int cur, int x1, int x2, int y1, int y2, int v, int op)
{
    if(inside(cur, x1, x2, y1, y2))
    {
        if(op == 1) Add(cur, v);
        else To(cur, v);
        return ;
    }
    st[cur].pushdown();
    for(int i = 0; i < 4; i ++)    
        if(st[cur].son[i] && inter(st[cur].son[i], x1, x2, y1, y2))
            refresh(st[cur].son[i], x1, x2, y1, y2, v, op);
    st[cur].update();
}
void query(int cur, int x1, int x2, int y1, int y2, int &sum, int &min, int &max)
{
    if(inside(cur, x1, x2, y1, y2))
    {
        sum += st[cur].sum, min = std::min(min, st[cur].min), max = std::max(max, st[cur].max);
        return ;
    }
    st[cur].pushdown();
    for(int i = 0; i < 4; i ++)
        if(st[cur].son[i] && inter(st[cur].son[i], x1, x2, y1, y2))
            query(st[cur].son[i], x1, x2, y1, y2, sum, min, max);
}
void solve()
{
    int i, op, x1, y1, x2, y2, v, min, max, sum;
    for(i = 0; i < P; i ++)
    {
        scanf("%d%d%d%d%d", &op, &x1, &y1, &x2, &y2);
        if(op == 3)
        {
            min = INF, max = -INF, sum = 0;
            query(1, x1, x2, y1, y2, sum, min, max);
            printf("%d %d %d\n", sum, min, max);
        }
        else
        {
            scanf("%d", &v);
            refresh(1, x1, x2, y1, y2, v, op);    
        }
    }
}
int main()
{
    while(scanf("%d%d%d", &N, &M, &P) == 3)
    {
        init();
        solve();    
    }    
    return 0;    
}
原文地址:https://www.cnblogs.com/staginner/p/2654429.html