传送门
题意:有一个n*n的二维数组,q次询问,每次询问一个二维区间的最大最小值并且将二维区间的中心的值更改为(最大值+最小值)/2
题解:rmq,如果不带修改则可以用倍增求rmq,带修改就用线段树,一维如此,二维也是如此,做的第一道二维线段树题,注意写法
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
//#define debug(x) cout<<#x<<" is "<<x<<endl;
const int maxn=805;
int a[maxn][maxn],n,ac1,ac2;
struct nod{
int rty;
int maxxy;
int minny;
};
struct Node{
int rtx;
struct nod y[maxn<<2];
}x[maxn<<2];
void pushupy(int rtx,int rty){
x[rtx].y[rty].maxxy=max(x[rtx].y[rty<<1].maxxy,x[rtx].y[(rty<<1)|1].maxxy);
x[rtx].y[rty].minny=min(x[rtx].y[rty<<1].minny,x[rtx].y[(rty<<1)|1].minny);
}
void buildy(int X,int rtx,int rt,int l,int r){
if(l==r){
if(X){
x[rtx].y[rt].maxxy=x[rtx].y[rt].minny=a[X][l];
}
else{
x[rtx].y[rt].maxxy=max(x[rtx<<1].y[rt].maxxy,x[(rtx<<1)|1].y[rt].maxxy);
x[rtx].y[rt].minny=min(x[rtx<<1].y[rt].minny,x[(rtx<<1)|1].y[rt].minny);
}
return;
}
int mid=(l+r)>>1;
buildy(X,rtx,rt<<1,l,mid);
buildy(X,rtx,(rt<<1)|1,mid+1,r);
pushupy(rtx,rt);
}
void buildx(int l,int r,int rt){
if(l==r){
buildy(l,rt,1,1,n);
return;
}
int mid=(l+r)>>1;
buildx(l,mid,rt<<1);
buildx(mid+1,r,(rt<<1)|1);
buildy(0,rt,1,1,n);
}
void updatey(int X,int Y,int rtx,int rt,int l,int r,int val){
if(l==r){
if(X){
x[rtx].y[rt].maxxy=x[rtx].y[rt].minny=val;
}
else{
x[rtx].y[rt].maxxy=max(x[rtx<<1].y[rt].maxxy,x[(rtx<<1)|1].y[rt].maxxy);
x[rtx].y[rt].minny=min(x[rtx<<1].y[rt].minny,x[(rtx<<1)|1].y[rt].minny);
}
return;
}
int mid=(l+r)>>1;
if(mid>=Y)updatey(X,Y,rtx,rt<<1,l,mid,val);
else updatey(X,Y,rtx,(rt<<1)|1,mid+1,r,val);
pushupy(rtx,rt);
}
void updatex(int X,int Y,int rt,int l,int r,int val){
if(l==r){
updatey(l,Y,rt,1,1,n,val);
return;
}
int mid=(l+r)>>1;
if(mid>=X)updatex(X,Y,rt<<1,l,mid,val);
else updatex(X,Y,(rt<<1)|1,mid+1,r,val);
updatey(0,Y,rt,1,1,n,val);
}
void queryy(int rtx,int y1,int y2,int rt,int l,int r){
if(l>=y1&&r<=y2){
ac1=max(x[rtx].y[rt].maxxy,ac1);
ac2=min(x[rtx].y[rt].minny,ac2);
return;
}
int mid=(l+r)>>1;
if(mid>=y1)queryy(rtx,y1,y2,rt<<1,l,mid);
if(mid<y2)queryy(rtx,y1,y2,(rt<<1)|1,mid+1,r);
}
void queryx(int x1,int y1,int x2,int y2,int rt,int l,int r){
if(l>=x1&&r<=x2){
queryy(rt,y1,y2,1,1,n);
return;
}
int mid=(l+r)>>1;
if(mid>=x1)queryx(x1,y1,x2,y2,rt<<1,l,mid);
if(mid<x2)queryx(x1,y1,x2,y2,(rt<<1)|1,mid+1,r);
}
int main(){
int t;
scanf("%d",&t);
int Ca=0;
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&a[i][j]);
}
}
buildx(1,n,1);
int q;
scanf("%d",&q);
printf("Case #%d:\n",++Ca);
while(q--){
int b,c,d;
scanf("%d%d%d",&b,&c,&d);
int x1=max(1,b-d/2);
int x2=min(n,b+d/2);
int y1=max(1,c-d/2);
int y2=min(n,c+d/2);
ac1=0;
ac2=0x3f3f3f3f;
queryx(x1,y1,x2,y2,1,1,n);
updatex(b,c,1,1,n,(ac1+ac2)/2);
printf("%d\n",(ac1+ac2)/2);
}
}
return 0;
}