HDU 4819 Mosaic(二维线段树)

给定一个矩阵,查询一块子矩阵的最大值和最小值,然后他们和的一半替换(x, y)这个位置,裸的二维线段树。

和一维差不多,只不过是一维当中保存的是最值,而这个保存的是个数组而已,而这个数组也是个一维的线段树,所以就是二维线段树。具体见代码注释。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1000;
//每个x节点上有个纵向的y数组,就是一列
struct Nodey {
    int l, r;
    int Max, Min;
};
int locx[maxn], locy[maxn];//对于给定的矩阵当中的位置(x, y)在线段树中对应的x和y的位置为locx[x], locy[y];
const int inf = 0x3f3f3f3f;
int T, n;//n矩阵的大小
struct Nodex {//x节点,就是普通的一维的线段树
    int l, r;
    Nodey sty[maxn<<2];//它的节点不是一个普通的值,而是一维的数组,其实就是一列
    void build(int rt, int ll, int rr)//对于一列建树,和一维一样,注意区分ll和l,ll是列当中的区间左值,而l是行当中的区间左值
    {
        sty[rt].l = ll;
        sty[rt].r = rr;
        sty[rt].Min = inf;
        sty[rt].Max = -inf;
        if (ll == rr)
        {
            locy[ll] = rt;//位置
            return;
        }
        int mid = (ll + rr) / 2;
        build(rt << 1, ll, mid);
        build(rt << 1 | 1, mid + 1, rr);
    }
    int queryMin(int rt, int ll, int rr)//查询列当中ll-rr区间当中的最值
    {
        if (sty[rt].l == ll && sty[rt].r == rr)
            return sty[rt].Min;
        int mid = (sty[rt].l + sty[rt].r) / 2;
        if (rr <= mid) return queryMin(rt << 1, ll, rr);
        else if (ll > mid) return queryMin(rt << 1 | 1, ll, rr);
        return min(queryMin(rt << 1, ll, mid), queryMin(rt << 1 | 1, mid + 1, rr));
    }
    int queryMax(int rt, int ll, int rr)
    {
        if (sty[rt].l == ll && sty[rt].r == rr)
            return sty[rt].Max;
        int mid = (sty[rt].l + sty[rt].r) / 2;
        if (rr <= mid) return queryMax(rt << 1, ll, rr);
        else if (ll > mid) return queryMax(rt << 1 | 1, ll, rr);
        return max(queryMax(rt << 1, ll, mid), queryMax(rt << 1 | 1, mid + 1, rr));
    }
}stx[maxn<<2];
void build(int rt, int l, int r)//建树
{
    stx[rt].l = l;
    stx[rt].r = r;
    stx[rt].build(1, 1, n);
    if (l == r)
    {
        locx[l] = rt;
        return;
    }
    int mid = (l + r) / 2;
    build(rt << 1, l, mid);
    build(rt << 1 | 1, mid + 1, r);
}
void modify(int x, int y, int val)//更改(x, y)这个点的值
{
    int tx = locx[x];
    int ty = locy[y];
    stx[tx].sty[ty].Min = stx[tx].sty[ty].Max = val;
    for (int i = tx; i; i >>= 1)//向上更新 PushUp
        for (int j = ty; j; j >>= 1)
        {
            if (i == tx && j == ty) continue;
            if (j == ty)
            {
                stx[i].sty[j].Min = min(stx[i<<1].sty[j].Min, stx[i<<1|1].sty[j].Min);
                stx[i].sty[j].Max = max(stx[i<<1].sty[j].Max, stx[i<<1|1].sty[j].Max);
            }
            else
            {
                stx[i].sty[j].Min = min(stx[i].sty[j<<1].Min, stx[i].sty[j<<1|1].Min);
                stx[i].sty[j].Max = max(stx[i].sty[j<<1].Max, stx[i].sty[j<<1|1].Max);
            }
        }
}
int queryMin(int rt, int x1, int x2, int y1, int y2)//查询在矩阵行为(x1 到 x2),列为(y1 到 y2)的最值
{
    if (stx[rt].l == x1 && stx[rt].r == x2)
        return stx[rt].queryMin(1, y1, y2);
    int mid = (stx[rt].l + stx[rt].r) / 2;
    if (x2 <= mid) return queryMin(rt << 1, x1, x2, y1, y2);
    else if (x1 > mid) return queryMin(rt << 1 | 1, x1, x2, y1, y2);
    return min(queryMin(rt << 1, x1, mid, y1, y2), queryMin(rt << 1 | 1, mid + 1, x2, y1, y2));
}
int queryMax(int rt, int x1, int x2, int y1, int y2)
{
    if (stx[rt].l == x1 && stx[rt].r == x2)
        return stx[rt].queryMax(1, y1, y2);
    int mid = (stx[rt].l + stx[rt].r) / 2;
    if (x2 <= mid) return queryMax(rt << 1, x1, x2, y1, y2);
    else if (x1 > mid) return queryMax(rt << 1 | 1, x1, x2, y1, y2);
    return max(queryMax(rt << 1, x1, mid, y1, y2), queryMax(rt << 1 | 1, mid + 1, x2, y1, y2));
}
int main()
{
    scanf("%d", &T);
    int kase = 0;
    while (T--)
    {
        scanf("%d", &n);
        build(1, 1, n);//建树
        int mat;
        printf("Case #%d:\n", ++kase);
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
            {
                scanf("%d", &mat);
                modify(i, j, mat);//更新
            }
        int q;
        scanf("%d", &q);
        while (q--)
        {
            int x, y, len;
            scanf("%d %d %d", &x, &y, &len);
            len /= 2;
            int x1 = max(x - len, 1);
            int x2 = min(x + len, n);
            int y1 = max(y - len, 1);
            int y2 = min(y + len, n);
            int Max = queryMax(1, x1, x2, y1, y2);
            int Min = queryMin(1, x1, x2, y1, y2);
            int ans = (Min + Max) / 2;
            printf("%d\n", ans);
            modify(x, y, ans);

        }
    }
    return 0;
}

 

posted @ 2015-10-13 11:56  Howe_Young  阅读(284)  评论(0编辑  收藏  举报