1.题目链接。二维线段树维护的使用。每一个节点都是一段区间,给这个区间建一颗线段树维护区间的信息。操作基本是类似的。
#include<bits/stdc++.h>
using namespace std;
const int INF = 1e9 + 10;
const int MAXN = 1010;
#pragma warning(disable:4996)
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 rt, int l, int r)
{
sty[rt].l = l;
sty[rt].r = r;
sty[rt].Max = -INF;
sty[rt].Min = INF;
if (l == r)
{
locy[l] = rt;
return;
}
int mid = (l + r) >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
}
int queryMin(int rt, int l, int r)
{
if (sty[rt].l == l && sty[rt].r == r)
return sty[rt].Min;
int mid = (sty[rt].l + sty[rt].r) >> 1;
if (r <= mid)
return queryMin(rt << 1, l, r);
else if (l > mid)
return queryMin(rt << 1 | 1, l, r);
else
{
return min(queryMin(rt << 1, l, mid), queryMin(rt << 1 | 1, mid + 1, r));
}
}
int queryMax(int rt, int l, int r)
{
if (sty[rt].l == r && sty[rt].r == r)
return sty[rt].Max;
int mid = (sty[rt].l + sty[rt].r) >> 1;
if (r <= mid)
return queryMax(rt << 1, l, r);
else if (l > mid)
return queryMax(rt << 1|1, l, r);
else
{
return max(queryMax(rt << 1, l, mid), queryMax(rt << 1 | 1, mid + 1, r));
}
}
}stx[MAXN*4];
int n;
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) >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
}
void update(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()
{
int T;
scanf("%d", &T);
int iCase = 0;
while (T--)
{
iCase++;
printf("Case #%d:\n", iCase);
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);
update(i, j, a);
}
int q;
int x, y, L;
scanf("%d", &q);
while (q--)
{
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);
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);
update(x, y, t);
}
}
return 0;
}