UVa 11297 - Census

题目:给定一个矩形的数组,在不断更新的过程中查询最值。

分析:线段树。利用矩形的左上和右下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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值