题目:给定一个矩形的数组,在不断更新的过程中查询最值。
分析:线段树。利用矩形的左上和右下2个顶点代表对应的矩形,建立矩形树。把每个矩形分成四个小矩形。设x3=(x1+x2)/2;y3=(y1+y2)/2,则矩形{(x1,y1),(x2,y2)}的四个孩子分别为{(x1,y1),(x3,y3)},{(x1,y3+1),(x3,y2)},{(x3+1,y1),(x2,y3)},{(x3+1,y3+1),(x2,y2)}。建树、更新和查询的方式和线段树相同。只是因为是二维的,所以每次先判断行的操作区间和对应节点区间的关系,再判断列区间对应的关系。判断条件变成一维的平方个了0_0。
注意:INT_MAX不在UVa的iostream和cstdlib库中,需要自己定义一个最值INF。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
#define INF (1<<30)
using namespace std;
//segment_tree__begin
typedef struct tnode
{
int X1,X2,Y1,Y2;
tnode* child[4];
int Min,Max;
}tnode;
tnode Node[ 500*500*2 ];
class segment_tree
{
private:
tnode* Root;
int Count;
tnode* madetree( int x1, int y1, int x2, int y2 ) {
tnode* np = &Node[ Count ++ ];
np->X1 = x1;
np->Y1 = y1;
np->X2 = x2;
np->Y2 = y2;
int x3 = (x1+x2)/2;
int y3 = (y1+y2)/2;
if ( x1 < x2 && y1 < y2 ) {
np->child[0] = madetree( x1, y1, x3, y3 );
np->child[1] = madetree( x3+1, y1, x2, y3 );
np->child[2] = madetree( x1, y3+1, x3, y2 );
np->child[3] = madetree( x3+1, y3+1, x2, y2 );
}else if ( x1 < x2 ) {
np->child[0] = madetree( x1, y1, x3, y3 );
np->child[1] = madetree( x3+1, y1, x2, y3 );
}else if ( y1 < y2 ) {
np->child[0] = madetree( x1, y1, x3, y3 );
np->child[2] = madetree( x1, y3+1, x3, y2 );
}
return np;
}
public:
segment_tree( int x1, int y1, int x2, int y2 ) {
Count = 0;
memset( Node, 0, sizeof( Node ) );
Root = madetree( x1, y1, x2, y2 );
}
void Insert( tnode* r, int x, int y, int v ) {
if ( r->X1 == x && r->Y1 == y && r->X2 == x && r->Y2 == y ) {
r->Max = r->Min = v;
return;
}
int x3 = (r->X1+r->X2)/2;
int y3 = (r->Y1+r->Y2)/2;
if ( x <= x3 ) {
if ( y <= y3 )
Insert( r->child[0], x, y, v );
else
Insert( r->child[2], x, y, v );
}else {
if ( y <= y3 )
Insert( r->child[1], x, y, v );
else
Insert( r->child[3], x, y, v );
}
r->Max = -INF;
r->Min = +INF;
for ( int i = 0 ; i < 4 ; ++ i )
if ( r->child[i] ) {
if ( r->Max < r->child[i]->Max )
r->Max = r->child[i]->Max;
if ( r->Min > r->child[i]->Min )
r->Min = r->child[i]->Min;
}
}
int Min( tnode* r, int x1, int y1, int x2, int y2 ) {
if ( r->X1 == x1 && r->Y1 == y1 && r->X2 == x2 && r->Y2 == y2 )
return r->Min;
int x3 = (r->X1+r->X2)/2;
int y3 = (r->Y1+r->Y2)/2;
if ( x2 <= x3 ) {
if ( y2 <= y3 )
return Min( r->child[0], x1, y1, x2, y2 );
else if ( y1 > y3 )
return Min( r->child[2], x1, y1, x2, y2 );
else
return min( Min( r->child[0], x1, y1, x2, y3 ),
Min( r->child[2], x1, y3+1, x2, y2 ) );
}else if ( x1 > x3 ) {
if ( y2 <= y3 )
return Min( r->child[1], x1, y1, x2, y2 );
else if ( y1 > y3 )
return Min( r->child[3], x1, y1, x2, y2 );
else
return min( Min( r->child[1], x1, y1, x2, y3 ),
Min( r->child[3], x1, y3+1, x2, y2 ) );
}else {
if ( y2 <= y3 )
return min( Min( r->child[0], x1, y1, x3, y2 ),
Min( r->child[1], x3+1, y1, x2, y2 ) );
else if ( y1 > y3 )
return min( Min( r->child[2], x1, y1, x3, y2 ),
Min( r->child[3], x3+1, y1, x2, y2 ) );
else
return min( min( Min( r->child[0], x1, y1, x3, y3 ),
Min( r->child[1], x3+1, y1, x2, y3 ) ),
min( Min( r->child[2], x1, y3+1, x3, y2 ),
Min( r->child[3], x3+1, y3+1, x2, y2 ) ) );
}
}
int Max( tnode* r, int x1, int y1, int x2, int y2 ) {
if ( r->X1 == x1 && r->Y1 == y1 && r->X2 == x2 && r->Y2 == y2 )
return r->Max;
int x3 = (r->X1+r->X2)/2;
int y3 = (r->Y1+r->Y2)/2;
if ( x2 <= x3 ) {
if ( y2 <= y3 )
return Max( r->child[0], x1, y1, x2, y2 );
else if ( y1 > y3 )
return Max( r->child[2], x1, y1, x2, y2 );
else
return max( Max( r->child[0], x1, y1, x2, y3 ),
Max( r->child[2], x1, y3+1, x2, y2 ) );
}else if ( x1 > x3 ) {
if ( y2 <= y3 )
return Max( r->child[1], x1, y1, x2, y2 );
else if ( y1 > y3 )
return Max( r->child[3], x1, y1, x2, y2 );
else
return max( Max( r->child[1], x1, y1, x2, y3 ),
Max( r->child[3], x1, y3+1, x2, y2 ) );
}else {
if ( y2 <= y3 )
return max( Max( r->child[0], x1, y1, x3, y2 ),
Max( r->child[1], x3+1, y1, x2, y2 ) );
else if ( y1 > y3 )
return max( Max( r->child[2], x1, y1, x3, y2 ),
Max( r->child[3], x3+1, y1, x2, y2 ) );
else
return max( max( Max( r->child[0], x1, y1, x3, y3 ),
Max( r->child[1], x3+1, y1, x2, y3 ) ),
max( Max( r->child[2], x1, y3+1, x3, y2 ),
Max( r->child[3], x3+1, y3+1, x2, y2 ) ) );
}
}
void Insert( int x, int y, int v ) {
Insert( Root, x, y, v );
}
int Min( int x1, int y1, int x2, int y2 ) {
return Min( Root, x1, y1, x2, y2 );
}
int Max( int x1, int y1, int x2, int y2 ) {
return Max( Root, x1, y1, x2, y2 );
}
};
//segment_tree__end
int C[ 501 ][ 501 ];
int main()
{
int N,M,Q,x1,y1,x2,y2,v;
char T;
while ( scanf("%d%d",&N,&M) != EOF ) {
segment_tree ST( 1, 1, N, M );
for ( int i = 1 ; i <= N ; ++ i )
for ( int j = 1 ; j <= M ; ++ j ) {
scanf("%d",&C[i][j]);
ST.Insert( i, j, C[i][j] );
}
scanf("%d",&Q);
for ( int i = 1 ; i <= Q ; ++ i ) {
T = ' ';
while ( T == ' ' || T == '\n' )
T = getchar();
if ( T == 'c' ) {
scanf("%d%d%d",&x1,&y1,&v);
ST.Insert( x1, y1, v );
}else {
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
printf("%d %d\n",ST.Max( x1, y1, x2, y2 ),ST.Min( x1, y1, x2, y2 ));
}
}
}
return 0;
}