您的位置:首页 > 大数据 > 人工智能

HDU 4819 Mosaic(二维线段树)

2015-10-13 11:56 501 查看
给定一个矩阵,查询一块子矩阵的最大值和最小值,然后他们和的一半替换(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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: