思路:就是构造二维线段树,然后就是单点跟新,区间最值了。
/*
题意:给你一个矩阵,随后m行,x,y,l,从x行y列,扩大l/2个格子,不能出界,表示要查询的矩阵大小,
查询最小值与最大值,然后将他们的和除
2输出来,然后将他们的和除2更新给 x,y。
思路:就是构造二维线段树,然后就是单点跟新,区间最值了。
*/
#include
#include
#include
#define MAX 801*4+10
#define inf 0x3f3f3f3f
int max1[MAX][MAX];
int min1[MAX][MAX];
int n;
int x1,x2,y1,y2;
int x,y,l;
int ma,mi;
int pd;
int max(int x,int y)
{
if(xy) return y;
return x;
}
void buildy(int rt,int left,int right,int xrt)//行线段树
{
if(left==right)
{
if(xrt==pd)//当着行是叶子行就输入
{
scanf("%d",&min1[xrt][rt]);
max1[xrt][rt]=min1[xrt][rt];
}
else//不是叶子行,就计算他两个儿子行的相对应列的位置的最值
{
min1[xrt][rt]=min(min1[xrt*2][rt],min1[xrt*2+1][rt]);
max1[xrt][rt]=max(max1[xrt*2][rt],max1[xrt*2+1][rt]);
}
return ;
}
int mid=(left+right)/2;
buildy(rt*2,left,mid,xrt);
buildy(rt*2+1,mid+1,right,xrt);
min1[xrt][rt]=min(min1[xrt][rt*2],min1[xrt][rt*2+1]);
max1[xrt][rt]=max(max1[xrt][rt*2],max1[xrt][rt*2+1]);
}
void build(int rt,int left,int right)//构造二维线段树列
{
int mid=(left+right)/2;
if(right>left)//当right==left表示分到了叶子节点则不必再分了。
{
build(rt*2,left,mid);
build(rt*2+1,mid+1,right);
}
if(right==left) pd=rt;//记录这是叶子行,等下是用来判断是否输入。
buildy(1,1,n,rt);
}
void updatey(int rt,int left,int right,int xrt,int c)//同建立的时候差不多。
{
if(left==right)
{
if(pd==xrt)
{
max1[xrt][rt]=min1[xrt][rt]=c;
}
else
{
min1[xrt][rt]=min(min1[xrt*2][rt],min1[xrt*2+1][rt]);
max1[xrt][rt]=max(max1[xrt*2][rt],max1[xrt*2+1][rt]);
}
return ;
}
int mid=(left+right)/2;
if(y<=mid) updatey(rt*2,left,mid,xrt,c);
if(y>mid) updatey(rt*2+1,mid+1,right,xrt,c);
min1[xrt][rt]=min(min1[xrt][rt*2],min1[xrt][rt*2+1]);
max1[xrt][rt]=max(max1[xrt][rt*2],max1[xrt][rt*2+1]);
}
void update(int rt,int left,int right,int c)
{
int mid=(left+right)/2;
if(right>left)
{
if(x<=mid) update(rt*2,left,mid,c);
if(x>mid) update(rt*2+1,mid+1,right,c);
}
if(left==right) pd=rt;//也是记录叶子行则用于跟新
updatey(1,1,n,rt,c);
}
void queryY(int rt,int left,int right,int xrt)
{
if(left>=y1&&right<=y2)//产寻到了对应的列
{
ma=max(ma,max1[xrt][rt]);
mi=min(mi,min1[xrt][rt]);
return ;
}
int mid=(left+right)/2;
if(y1<=mid) queryY(rt*2,left,mid,xrt);
if(y2>mid) queryY(rt*2+1,mid+1,right,xrt);
}
void query(int rt,int left,int right)
{
if(left>=x1&&right<=x2)//查询到了对应的行。
{
queryY(1,1,n,rt);
return ;
}
int mid=(left+right)/2;
if(x1<=mid) query(rt*2,left,mid);
if(x2>mid) query(rt*2+1,mid+1,right);
}
int main()
{
int t;
int cas=1;
scanf("%d",&t);
while(t--)
{
memset(max1,-inf,sizeof(max1));
memset(min1,inf,sizeof(min1));
printf("Case #%d:\n",cas++);
scanf("%d",&n);
pd=-1;
build(1,1,n);
int q;
scanf("%d",&q);
while(q--)
{
scanf("%d %d %d",&x,&y,&l);
l/=2;
x1=max(1,x-l);x2=min(n,x+l);//计算矩阵向两边扩展的大小
y1=max(1,y-l);y2=min(n,y+l);
ma=-inf;mi=inf;
query(1,1,n);
printf("%d\n",(ma+mi)/2);
pd=-1;
update(1,1,n,(ma+mi)/2);
}
}
return 0;
}