#树套树,二维线段树#HDU 4819 Mosaic
题目
多组数据,给定一个\(n*n\)的矩阵(\(n\leq 80,a_{i,j}\leq 10^9\))
多组询问一个以\((x,y)\)为中心,边长为\(L\)的子矩阵最大值\(mx\)和最小值\(mn\),
并将\((x,y)\)这一个位置修改为\(\lfloor\frac{mn+mx}{2}\rfloor\),每次询问输出修改后的\((x,y)\)
分析
二维线段树裸题,反正之前也没敲过,
其实和一维线段树相近,找到\(lx\sim rx\)的下标
再按照一维线段树的方式修改最大最小值就可以了
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=801,M=3201; struct rec{int x,y;};
int wmn[M][M],wmx[M][M],ans,n,a[N][N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline signed min(int a,int b){return a<b?a:b;}
inline signed max(int a,int b){return a>b?a:b;}
inline void pupx(int kx,int ky){
wmn[kx][ky]=min(wmn[kx<<1][ky],wmn[kx<<1|1][ky]);
wmx[kx][ky]=max(wmx[kx<<1][ky],wmx[kx<<1|1][ky]);
}
inline void pupy(int kx,int ky){
wmn[kx][ky]=min(wmn[kx][ky<<1],wmn[kx][ky<<1|1]);
wmx[kx][ky]=max(wmx[kx][ky<<1],wmx[kx][ky<<1|1]);
}
inline void buildy(int ky,int kx,int l,int r,int z){
if (l==r){
if (z) wmn[kx][ky]=wmx[kx][ky]=a[z][l];
else pupx(kx,ky);
return;
}
rr int mid=(l+r)>>1;
buildy(ky<<1,kx,l,mid,z);
buildy(ky<<1|1,kx,mid+1,r,z);
pupy(kx,ky);
}
inline void buildx(int k,int l,int r){
if (l==r){
buildy(1,k,1,n,l);
return;
}
rr int mid=(l+r)>>1;
buildx(k<<1,l,mid);
buildx(k<<1|1,mid+1,r);
buildy(1,k,1,n,0);
}
inline void updatey(rec K,int l,int r,rec t,int z){
if (l==t.x&&r==t.y){
if (z) wmn[K.x][K.y]=wmx[K.x][K.y]=ans;
else pupx(K.x,K.y);
return;
}
rr int mid=(l+r)>>1;
if (t.y<=mid) updatey((rec){K.x,K.y<<1},l,mid,t,z);
else if (t.x>mid) updatey((rec){K.x,K.y<<1|1},mid+1,r,t,z);
else {
updatey((rec){K.x,K.y<<1},l,mid,(rec){t.x,mid},z);
updatey((rec){K.x,K.y<<1|1},mid+1,r,(rec){mid+1,t.y},z);
}
pupy(K.x,K.y);
}
inline void updatex(int k,int l,int r,rec L,rec R){
if (l==L.x&&r==L.y){
updatey((rec){k,1},1,n,R,1);
return;
}
rr int mid=(l+r)>>1;
if (L.y<=mid) updatex(k<<1,l,mid,L,R);
else if (L.x>mid) updatex(k<<1|1,mid+1,r,L,R);
else {
updatex(k<<1,l,mid,(rec){L.x,mid},R);
updatex(k<<1|1,mid+1,r,(rec){mid+1,L.y},R);
}
updatey((rec){k,1},1,n,R,0);
}
inline void queryy(rec K,int l,int r,rec t,int &mn,int &mx){
if (l==t.x&&r==t.y){
mn=min(mn,wmn[K.x][K.y]),
mx=max(mx,wmx[K.x][K.y]);
return;
}
rr int mid=(l+r)>>1;
if (t.y<=mid) queryy((rec){K.x,K.y<<1},l,mid,t,mn,mx);
else if (t.x>mid) queryy((rec){K.x,K.y<<1|1},mid+1,r,t,mn,mx);
else {
queryy((rec){K.x,K.y<<1},l,mid,(rec){t.x,mid},mn,mx);
queryy((rec){K.x,K.y<<1|1},mid+1,r,(rec){mid+1,t.y},mn,mx);
}
}
inline void queryx(int k,int l,int r,rec L,rec R,int &mn,int &mx){
if (l==L.x&&r==L.y){
queryy((rec){k,1},1,n,R,mn,mx);
return;
}
rr int mid=(l+r)>>1;
if (L.y<=mid) queryx(k<<1,l,mid,L,R,mn,mx);
else if (L.x>mid) queryx(k<<1|1,mid+1,r,L,R,mn,mx);
else {
queryx(k<<1,l,mid,(rec){L.x,mid},R,mn,mx);
queryx(k<<1|1,mid+1,r,(rec){mid+1,L.y},R,mn,mx);
}
}
signed main(){
for (rr int Test=iut(),T=1;T<=Test;++T){
printf("Case #%d:\n",T),n=iut();
for (rr int i=1;i<=n;++i)
for (rr int j=1;j<=n;++j) a[i][j]=iut();
buildx(1,1,n);
for (rr int Q=iut();Q;--Q){
rr int x=iut(),y=iut(),L=(iut()-1)>>1;
rr int lx=max(x-L,1),ly=max(y-L,1),mx=0;
rr int rx=min(x+L,n),ry=min(y+L,n),mn=1e9;
queryx(1,1,n,(rec){lx,rx},(rec){ly,ry},mn,mx),
ans=(mx+mn)>>1,lx=rx=x,ly=ry=y;
print(ans),putchar(10),
updatex(1,1,n,(rec){lx,rx},(rec){ly,ry});
}
}
return 0;
}