hdu 4819 二维线段树模板

/*
HDU 4819 Mosaic
题意:查询某个矩形内的最大最小值,
      修改矩形内某点的值为该矩形(Mi+MA)/2;
二维线段树模板:
    区间最值,单点更新。
*/
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 1010;
int N, Q;
struct Nodey
{
    int l, r;
    int Max, Min;
};
int locx[MAXN], locy[MAXN];
struct Nodex
{
    int l, r;
    Nodey sty[MAXN * 4];
    void build(int i, int _l, int _r)
    {
        sty[i].l = _l;
        sty[i].r = _r;
        sty[i].Max = -INF;
        sty[i].Min = INF;
        if(_l == _r)
        {
            locy[_l] = i;
            return;
        }
        int mid = (_l + _r) / 2;
        build(i << 1, _l, mid);
        build((i << 1) | 1, mid + 1, _r);
    }
    int queryMin(int i, int _l, int _r)
    {
        if(sty[i].l == _l && sty[i].r == _r)
            return sty[i].Min;
        int mid = (sty[i].l + sty[i].r) / 2;
        if(_r <= mid)
            return queryMin(i << 1, _l, _r);
        else if(_l > mid)
            return queryMin((i << 1) | 1, _l, _r);
        else
            return min(queryMin(i << 1, _l, mid), queryMin((i << 1) | 1, mid + 1, _r));
    }
    int queryMax(int i, int _l, int _r)
    {
        if(sty[i].l == _l && sty[i].r == _r)
            return sty[i].Max;
        int mid = (sty[i].l + sty[i].r) / 2;
        if(_r <= mid)
            return queryMax(i << 1, _l, _r);
        else if(_l > mid)
            return queryMax((i << 1) | 1, _l, _r);
        else
            return max(queryMax(i << 1, _l, mid), queryMax((i << 1) | 1, mid + 1, _r));
    }
} stx[MAXN * 4];
void build(int i, int l, int r)
{
    stx[i].l = l;
    stx[i].r = r;
    stx[i].build(1, 1, N);
    if(l == r)
    {
        locx[l] = i;
        return;
    }
    int mid = (l + r) / 2;
    build(i << 1, l, mid);
    build((i << 1) | 1, mid + 1, r);
}
//单点修改值
void Modify(int x, int y, int val)
{
    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)
        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 i, int x1, int x2, int y1, int y2)
{
    if(stx[i].l == x1 && stx[i].r == x2)
        return stx[i].queryMin(1, y1, y2);
    int mid = (stx[i].l + stx[i].r) / 2;
    if(x2 <= mid)
        return queryMin(i << 1, x1, x2, y1, y2);
    else if(x1 > mid)
        return queryMin((i << 1) | 1, x1, x2, y1, y2);
    else
        return min(queryMin(i << 1, x1, mid, y1, y2), queryMin((i << 1) | 1, mid + 1, x2, y1, y2));
}
int queryMax(int i, int x1, int x2, int y1, int y2)
{
    if(stx[i].l == x1 && stx[i].r == x2)
        return stx[i].queryMax(1, y1, y2);
    int mid = (stx[i].l + stx[i].r) / 2;
    if(x2 <= mid)
        return queryMax(i << 1, x1, x2, y1, y2);
    else if(x1 > mid)
        return queryMax((i << 1) | 1, x1, x2, y1, y2);
    else
        return max(queryMax(i << 1, x1, mid, y1, y2), queryMax((i << 1) | 1, mid + 1, x2, y1, y2));
}

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int T, ic = 0;
    scanf("%d", &T);
    while(T--)
    {
        printf("Case #%d:\n", ++ic);
        scanf("%d", &N);
        build(1, 1, N);
        for(int i = 1; i <= N; i++)
            for(int j = 1; j <= N; j++)
            {
                int a;
                scanf("%d", &a);
                Modify(i, j, a);
            }
        scanf("%d", &Q);
        while(Q--)
        {
            int x, y, L;
            scanf("%d%d%d", &x, &y, &L);
            int x1 = max(x - L / 2, 1);
            int x2 = min(x + L / 2, N);
            int y1 = max(y - L / 2, 1);
            int y2 = min(y + L / 2, N);
            //(x1,y1)左上角,(x2,y2)右下角
            int Max = queryMax(1, x1, x2, y1, y2);
            int Min = queryMin(1, x1, x2, y1, y2);
            int t = (Max + Min) / 2;
            printf("%d\n", t);
            Modify(x, y, t);//单点修改
        }
    }
    return 0;
}
时间: 2024-08-25 14:28:00

hdu 4819 二维线段树模板的相关文章

【HDU 4819】Mosaic 二维线段树模板

二维线段树的模板题,和一维一样的思路,更新的时候注意一下细节. 存模板: /* 二维线段树模板整理 */ #include<cstdio> #include<algorithm> using namespace std; #define lson (pos<<1) #define rson (pos<<1|1) const int maxn = 805; const int INF = (1 << 30); int n; int posX[max

HDU 1823 二维线段树(区间max)

Luck and Love Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5262    Accepted Submission(s): 1317 Problem Description 世界上上最远的距离不是相隔天涯海角而是我在你面前可你却不知道我爱你                ―― 张小娴 前段日子,枫冰叶子给Wiskey做了

HDU 1823 二维线段树

二维线段树入门题 分别以身高和活泼度开两维 以身高-100,活泼度*10,为两个区间 所谓的二维就是在第一维查找到正确位置时,进入第二维再查找 #include "stdio.h" #include "string.h" double ans; double Max(double a,double b) { if (a<b) return b;else return a; } struct Mark { int l,r; double x; }; struct

二维线段树模版

HDU 4819 二维线段树模版题 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int INF = 999999999; const int maxn = 810; int a[maxn][maxn]; int st_min[maxn<<2][maxn<<2]; int st_max[maxn<<2][maxn

HDU1832 二维线段树求最值(模板)

Luck and Love Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 50 Accepted Submission(s): 20   Problem Description 世界上上最远的距离不是相隔天涯海角而是我在你面前可你却不知道我爱你                ―― 张小娴 前段日子,枫冰叶子给Wiskey做了个征婚启事,聘

UVA 11297 Census ——二维线段树

[题目分析] 二维线段树模板题目. 简直就是无比的暴力.时间复杂度为两个log. 标记的更新方式比较奇特,空间复杂度为N^2. 模板题目. [代码] #include <cstdio> #include <cstring> //#include <cmath> #include <cstdlib> #include <map> #include <set> #include <queue> #include <str

Luck and Love(二维线段树)

Luck and Love Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 54 Accepted Submission(s): 21   Problem Description 世界上上最远的距离不是相隔天涯海角而是我在你面前可你却不知道我爱你                ―― 张小娴 前段日子,枫冰叶子给Wiskey做了个征婚启事,聘

Uva 11297.Census——二维线段树

http://www.bnuoj.com/v3/problem_show.php?pid=19715 二维线段树模板 #include <cstring> #include <cstdio> #include <algorithm> #include <iostream> #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define rep(i,n) for(int i=0

HDU 4819 Mosaic --二维线段树(树套树)

题意: 给一个矩阵,每次查询一个子矩阵内的最大最小值,然后更新子矩阵中心点为(Max+Min)/2. 解法: 由于是矩阵,且要求区间最大最小和更新单点,很容易想到二维的线段树,可是因为之前没写过二维的线段树,所以没跳出来.后来熟悉了一下,原来很多细节地方都没有考虑到. 这里build,update,query都分为两个函数,第一个为Y轴的(sub_update),第二个为X轴的(update),不仅每个sub_update或sub_build后面要加Y轴的pushup函数,而且每个update或