2013长春区域赛, 二维线段树, 单点更新 + 区间查询(存个模板)
题意:给定一个矩阵, 对于x, y, d, 将x, y的值更新为以x, y为中心的小矩阵中最大值和最小值的一半
分析:二维线段树,区间查询最大值和最小值, 单点更新x, y这一点
#include
#include
#include
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 800 * 4 + 10;
int mx[maxn][maxn], mi[maxn][maxn];
int x, y, x1, y1, x2, y2, d, n;
int xo, xleaf, v;
int ans1, ans2;
int t, ca = 1;
void update2(int o, int l, int r) {
if (l == r) {
if (xleaf) {
mx[xo][o] = mi[xo][o] = v;
}
else {
mx[xo][o] = max(mx[2 * xo][o], mx[2 * xo + 1][o]);
mi[xo][o] = min(mi[2 * xo][o], mi[2 * xo + 1][o]);
}
return;
}
int mid = (l + r) >> 1;
if (y <= mid) update2(2 * o, l, mid);
else update2(2 * o + 1, mid + 1, r);
mx[xo][o] = max(mx[xo][2 * o], mx[xo][2 * o + 1]);
mi[xo][o] = min(mi[xo][2 * o], mi[xo][2 * o + 1]);
}
void update1(int o, int l, int r) {
if (l == r) {
xo = o;
xleaf = 1;
update2(1, 1, n);
return;
}
int mid = (l + r) >> 1;
if (x <= mid) update1(2 * o, l, mid);
else update1(2 * o + 1, mid + 1, r);
xo = o;
xleaf = 0;
update2(1, 1, n);
}
void update() {
update1(1, 1, n);
}
void query2(int o, int l, int r) {
if (y1 <= l && y2 >= r) {
ans1 = min(ans1, mi[xo][o]);
ans2 = max(ans2, mx[xo][o]);
return;
}
int mid = (l + r) >> 1;
if (y1 <= mid) query2(2 * o, l, mid);
if (y2 > mid) query2(2 * o + 1, mid + 1, r);
}
void query1(int o, int l, int r) {
if (x1 <= l && x2 >= r) {
xo = o;
query2(1, 1, n);
return;
}
int mid = (l + r) >> 1;
if (x1 <= mid) query1(2 * o, l, mid);
if (x2 > mid) query1(2 * o + 1, mid + 1, r);
}
void query() {
ans1 = inf;
ans2 = -inf;
query1(1, 1, n);
}
int main() {
scanf("%d", &t);
while (t --) {
scanf("%d", &n);
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= n; j ++) {
scanf("%d", &v);
x = i, y = j;
update();
}
}
int q;
scanf("%d", &q);
printf("Case #%d:\n", ca ++);
while (q --) {
scanf("%d%d%d", &x, &y, &d);
d = (d - 1) >> 1;
x1 = max(1, x - d);
y1 = max(1, y - d);
x2 = min(n, x + d);
y2 = min(n, y + d);
query();
v = (ans1 + ans2) >> 1;
printf("%d\n", v);
update();
}
}
return 0;
}
/*
1
3
1 2 3
4 5 6
7 8 9
5
2 2 1
3 2 3
1 1 3
1 2 3
2 2 3
*/