#树套树,二维线段树#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;
}
posted @ 2020-03-22 23:27  lemondinosaur  阅读(121)  评论(0编辑  收藏  举报