题目:给定一个矩形的数组,在不断更新的过程中查询最值。
分析:线段树。利用矩形的左上和右下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;
}

本文介绍了一种使用二维线段树解决矩形数组更新及查询最大值问题的方法。通过将矩形区域划分为四个子区域并递归构建树结构,实现了高效的更新与查询操作。
340

被折叠的 条评论
为什么被折叠?



