zoukankan      html  css  js  c++  java
  • 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:
    ", ++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
    ", ans);
                modify(x, y, ans);
    
            }
        }
        return 0;
    }
  • 相关阅读:
    78. Subsets
    93. Restore IP Addresses
    71. Simplify Path
    82. Remove Duplicates from Sorted List II
    95. Unique Binary Search Trees II
    96. Unique Binary Search Trees
    312. Burst Balloons
    程序员社交平台
    APP Store开发指南
    iOS框架搭建(MVC,自定义TabBar)--微博搭建为例
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/4874176.html
Copyright © 2011-2022 走看看