#树套树,二维线段树#HDU 4819 Mosaic

Posted spare-no-effort

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#树套树,二维线段树#HDU 4819 Mosaic相关的知识,希望对你有一定的参考价值。

题目

多组数据,给定一个(n*n)的矩阵((nleq 80,a_{i,j}leq 10^9))
多组询问一个以((x,y))为中心,边长为(L)的子矩阵最大值(mx)和最小值(mn)
并将((x,y))这一个位置修改为(lfloorfrac{mn+mx}{2} floor),每次询问输出修改后的((x,y))


分析

二维线段树裸题,反正之前也没敲过,
其实和一维线段树相近,找到(lxsim 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:
",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;
}

以上是关于#树套树,二维线段树#HDU 4819 Mosaic的主要内容,如果未能解决你的问题,请参考以下文章

HDU4819 Mosaic树套树

hdu-4819-线段树套线段树

二维线段树之树套树

知识点 - 线段树 权值 树套树 二维 可持续

树套树+UVALive6709 Mosaic 二维线段树

[POJ2155] Matrix(二维线段树,树套树)