现在的位置: 首页 > 综合 > 正文

【COGS】451 布匠问题 四分树

2017年11月20日 ⁄ 综合 ⁄ 共 2352字 ⁄ 字号 评论关闭

传送门:【COGS】451 布匠问题

题目分析:这题一看就是二维线段树区间修改区间查询啊,可是。。。写了一下午还是写不出来。。。后来索性暴力1000棵线段树,然后T了三组数据。。。感觉没治了。。。

后来突然想到是不是可以写四分树(四个儿子的线段树),每一个儿子都是一个矩阵,叶子节点就是1X1的矩阵,然后就这么YY了个写法写了下,然后让我十分无语的是:我竟然AC了。。。。。竟然AC了!

迫不及待的想去仰慕大神们的写法(AC了一题以后可以看其他人AC这题的代码),然后更让我无语的是!他们全部是暴力的!!!各种暴力无节操啊有木有!!

我的眼泪忍不住就哗哗哗的流啊T U T。。。

代码如下:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

#define REP( i , a , b ) for ( int i = ( a ) ; i <  ( b ) ; ++ i )
#define FOR( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
#define REV( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define CLR( a , x ) memset ( a , x , sizeof a )
#define CPY( a , x ) memcpy ( a , x , sizeof a )
#define s1 o * 4 + 1
#define s2 o * 4 + 2
#define s3 o * 4 + 3
#define s4 o * 4 + 4
#define son1 s1 , lx , mx , ly , my
#define son2 s2 , lx , mx , my + 1 , ry
#define son3 s3 , mx + 1 , rx , ly , my
#define son4 s4 , mx + 1 , rx , my + 1 , ry
#define root  0 , 1 , n , 1 , m
#define rt o , lx , rx , ly , ry
#define xxyy x1 , x2 , y1 , y2

const int MAXN = 5000005 ;

int sum[MAXN] ;
int set[MAXN] ;

void pushdown ( int o , int lx , int rx , int ly , int ry ) {
	if ( ~set[o] ) {
		int mx = ( lx + rx ) >> 1 , my = ( ly + ry ) >> 1 ;
		set[s1] = set[o] , sum[s1] = set[o] ? ( mx - lx + 1 ) * ( my - ly + 1 ) : 0 ;
		set[s2] = set[o] , sum[s2] = set[o] ? ( mx - lx + 1 ) * ( ry - my ) : 0 ;
		set[s3] = set[o] , sum[s3] = set[o] ? ( rx - mx ) * ( my - ly + 1 ) : 0 ;
		set[s4] = set[o] , sum[s4] = set[o] ? ( rx - mx ) * ( ry - my ) : 0 ;
		set[o] = -1 ;
	}
}

void update ( int v , int x1 , int x2 , int y1 , int y2 , int o , int lx , int rx , int ly , int ry ) {
	if ( x1 <= lx && rx <= x2 && y1 <= ly && ry <= y2 ) {
		set[o] = v ;
		sum[o] = v ? ( rx - lx + 1 ) * ( ry - ly + 1 ) : 0 ;
		return ;
	}
	pushdown ( rt ) ;
	int mx = ( lx + rx ) >> 1 , my = ( ly + ry ) >> 1 ;
	if ( x1 <= mx && y1 <= my ) update ( v , xxyy , son1 ) ;
	if ( x1 <= mx && my <  y2 ) update ( v , xxyy , son2 ) ;
	if ( mx <  x2 && y1 <= my ) update ( v , xxyy , son3 ) ;
	if ( mx <  x2 && my <  y2 ) update ( v , xxyy , son4 ) ;
	sum[o] = sum[s1] + sum[s2] + sum[s3] + sum[s4] ;
}

int query ( int x1 , int x2 , int y1 , int y2 , int o , int lx , int rx , int ly , int ry ) {
	if ( x1 <= lx && rx <= x2 && y1 <= ly && ry <= y2 ) return sum[o] ;
	pushdown ( rt ) ;
	int mx = ( lx + rx ) >> 1 , my = ( ly + ry ) >> 1 , ans = 0 ;
	if ( x1 <= mx && y1 <= my ) ans += query ( xxyy , son1 ) ;
	if ( x1 <= mx && my <  y2 ) ans += query ( xxyy , son2 ) ;
	if ( mx <  x2 && y1 <= my ) ans += query ( xxyy , son3 ) ;
	if ( mx <  x2 && my <  y2 ) ans += query ( xxyy , son4 ) ;
	return ans ;
}

void scanf ( int& x , char c = 0 ) {
	while ( ( c = getchar () ) < '0' || c > '9' ) ;
	x = c - '0' ;
	while ( ( c = getchar () ) >= '0' && c <= '9' ) x = x * 10 + c - '0' ;
}

void solve () {
	int n , m , q ;
	int op , x1 , x2 , y1 , y2 ;
	scanf ( "%d%d%d" , &n , &m , &q ) ;
	CLR ( sum , 0 ) ;
	CLR ( set , -1 ) ;
	while ( q -- ) {
		scanf ( op ) , scanf ( x1 ) , scanf ( y1 ) , scanf ( x2 ) , scanf ( y2 ) ;
		//printf ( "ok\n" ) ;
		if ( op == 0 ) {
			printf ( "%d\n" , query ( xxyy , root ) ) ;
		} else update ( 2 - op , xxyy , root ) ;
		//printf ( "ok\n" ) ;
	}
}

int main () {
	freopen ( "fabric.in" , "r" , stdin ) ;
	freopen ( "fabric.out" , "w" , stdout ) ;
	solve () ;
	return 0 ;
}

抱歉!评论已关闭.