题目:http://acm.hdu.edu.cn/showproblem.php?pid=4819
传说中长春赛区出现的很裸的二维线段树,从没写过二维的窝表示撸了一个晚上的代码,颤抖着点了个submit居然还特么地1Y了。。。
好吧,题意是给定一个初始的N*N矩阵以及每个方格的值,每次给出x, y, l,找到以(x,y)为中心的l*l大小的矩阵,l保证为奇数,找到这个矩阵中的最大值和最小值,然后求出它们的平均数,将(x,y)修改为平均数,并输出平均数。如果小矩阵有部分跑出大矩阵,跑出去的部分是忽略掉的。
感觉写得很搓的样子,貌似连所谓的懒惰标记都没有(虽然这题是单点更新,但重点是智商不够了= =)。
大概就是先按着X建立线段树,每个节点再建立Y的线段树。
查询和更新都是先按找X,然后找Y。
还是留个纪念吧。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 801
#define LEFT(o) ((o)<<1)
#define RIGHT(o) (((o)<<1)|1)
int t, n, q, x1, x2, y1, y2;
int map[N][N];
int lx[N<<2], rx[N<<2], ly[N<<2], ry[N<<2];
int A[N<<2][N<<2], B[N<<2][N<<2];
void maintain(int po, int o){
A[po][o] = max(A[po][LEFT(o)], A[po][RIGHT(o)]);
B[po][o] = min(B[po][LEFT(o)], B[po][RIGHT(o)]);
}
void buildY(int po, int o, int ll, int rr){
ly[o]=ll; ry[o]=rr;
if(ll<rr){
int m = (ll+rr)>>1;
buildY(po, LEFT(o), ll, m);
buildY(po, RIGHT(o), m+1, rr);
maintain(po, o);
}
else{
if(lx[po]==rx[po]){
A[po][o] = B[po][o] = map[lx[po]][ll];
}
else{
A[po][o] = max(A[LEFT(po)][o], A[RIGHT(po)][o]);
B[po][o] = min(B[LEFT(po)][o], B[RIGHT(po)][o]);
}
}
}
void buildX(int o, int ll, int rr){
lx[o]=ll; rx[o]=rr;
if(ll<rr){
int m=(ll+rr)>>1;
buildX(LEFT(o), ll, m);
buildX(RIGHT(o), m+1, rr);
}
buildY(o, 1, 1, n);
}
void updateY(int po, int o, int ll, int rr, int v){
//printf("UY: %d %d %d %d\n", lx[po], rx[po], ly[o], ry[o]);
if(ly[o]==ry[o]){
if(lx[po]==rx[po]) A[po][o] = B[po][o] = v;
else{
A[po][o] = max(A[LEFT(po)][o], A[RIGHT(po)][o]);
B[po][o] = min(B[LEFT(po)][o], B[RIGHT(po)][o]);
}
return;
}
int m = (ly[o]+ry[o])>>1;
if(rr<=m) updateY(po, LEFT(o), ll, rr, v);
else if(ll>m) updateY(po, RIGHT(o), ll, rr, v);
else{
updateY(po, LEFT(o), ll, m, v);
updateY(po, RIGHT(o), m+1, rr, v);
}
maintain(po, o);
}
void updateX(int o, int ll, int rr, int v){
//printf("UX: %d %d\n", lx[o], rx[o]);
if(lx[o]==rx[o]){
updateY(o, 1, y1, y2, v);
return;
}
int m = (lx[o]+rx[o])>>1;
if(rr<=m) updateX(LEFT(o), ll, rr, v);
else if(ll>m) updateX(RIGHT(o), ll, rr, v);
else{
updateX(LEFT(o), ll, m, v);
updateX(RIGHT(o), m+1, rr, v);
}
updateY(o, 1, y1, y2, v);
}
void queryY(int po, int o, int ll, int rr, int& a,int& b){
// printf("QY: %d %d %d %d\n", lx[po], rx[po], ly[o], ry[o]);
if(ly[o]==ll && ry[o]==rr){
a = A[po][o]; b = B[po][o];
// printf("bot: %d %d\n", a, b);
return;
}
int m = (ly[o]+ry[o])>>1;
int a1, a2, b1, b2;
if(rr<=m) queryY(po, LEFT(o), ll, rr, a1, b1);
else if(ll>m) queryY(po, RIGHT(o), ll, rr, a1, b1);
else{
queryY(po, LEFT(o), ll, m, a1, b1);
queryY(po, RIGHT(o), m+1, rr, a2, b2);
a1 = max(a1, a2);
b1 = min(b1, b2);
}
a=a1; b=b1;
//printf("%d %d : %d %d\n", ly[o], ry[o], a, b);
}
void queryX(int o, int ll, int rr, int& a, int& b){
//printf("QX: %d %d\n", lx[o], rx[o]);
if(lx[o]==ll && rx[o]==rr){
queryY(o, 1, y1, y2, a, b);
return;
}
int m = (lx[o]+rx[o])>>1;
int a1, a2, b1, b2;
if(rr<=m) queryX(LEFT(o), ll, rr, a1, b1);
else if(ll>m) queryX(RIGHT(o), ll, rr, a1, b1);
else{
queryX(LEFT(o), ll, m, a1, b1);
queryX(RIGHT(o), m+1, rr, a2, b2);
a1 = max(a1, a2);
b1 = min(b1, b2);
}
a=a1; b=b1;
}
int main(){
scanf("%d", &t);
for(int ct=1; ct<=t; ct++){
scanf("%d", &n);
for(int i=1;i<=n; i++){
for(int j=1; j<=n; j++){
scanf("%d", &map[i][j]);
}
}
buildX(1, 1, n);
scanf("%d", &q);
printf("Case #%d:\n", ct);
int x, y, l;
while(q--){
scanf("%d %d %d", &x, &y, &l);
l>>=1;
x1 = max(x-l, 1);
x2 = min(x+l, n);
y1 = max(y-l, 1);
y2 = min(y+l, n);
//printf("q: %d %d %d %d\n", x1, y1, x2, y2);
int a, b;
queryX(1, x1, x2, a, b);
// printf("g: %d %d\n", a, b);
a = (a+b)>>1;
x1=x2=x; y1=y2=y;
updateX(1, x1, x2, a);
printf("%d\n", a);
}
}
return 0;
}