HDU1255 矩阵面积交线段树扫描线

HDU1255

思路:线段树扫描线,跟面积并不同的一点是这个需要维护一个至少两条下边的和一个至少一条下边的长度。
Code:

#include 
#define LL long long 
using namespace std ;
const int AX = 4e3 + 66 ; 
struct Node{
	double l , r , y ;
	LL cov ;
	Node(){};
	Node( double l , double r , double y , LL cov ):l(l),r(r),y(y),cov(cov){}
	bool operator < ( const Node &ch )const{
		return y < ch.y ;
	} 
}line[AX];
vector<double> X;
double sum[AX<<2] ;	//至少2条下边
double one[AX<<2] ;  //至少1条下边
LL mark[AX<<2] ; 
void pushUp( int rt , int l , int r ){
	if( mark[rt] >= 2 ){ sum[rt] = one[rt] = X[r] - X[l-1] ; }
	else if( mark[rt] == 1 ){
		one[rt] = X[r] - X[l-1];
        if( l == r ) sum[rt] = 0;
        else sum[rt] = one[rt << 1] + one[rt << 1 | 1];
	}else{
		 if(l == r) one[rt] = sum[rt] = 0;
        else {
            one[rt] = one[rt << 1] + one[rt << 1 | 1];
            sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
        }
	}
} 

void update( int L , int R , int cov , int l , int r , int rt ){
	if( L <= l && R >= r ){
		mark[rt] += cov ; 
		pushUp( rt , l , r ) ;
		return ; 
	}
	int mid = ( l + r ) >> 1 ; 
	if( L <= mid ) update( L , R , cov , l , mid , rt << 1 ) ;
	if( R > mid ) update( L , R , cov , mid + 1 , r , rt << 1 | 1 ) ; 
	pushUp( rt , l , r ) ;
}

int main(){
	int n ;
	int T ; 
	scanf("%d",&T) ; 
	while( T-- ){
		memset( one , 0 , sizeof(one) );
		memset( sum , 0 , sizeof(sum) );
		memset( mark , 0 , sizeof(mark) );
		scanf("%d",&n) ; 
		X.clear() ; 
		double x1 , y1 , x2 , y2 ; 
		int num = 0 ; 
		while( n-- ){
			scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
			X.push_back(x1) ; 
			line[num++] = Node( x1 , x2 , y1 , 1 ) ;
			X.push_back(x2) ; 
			line[num++] = Node( x1 , x2 , y2 , -1 ) ;
		}
		sort( line , line + num ) ; 
		sort( X.begin() , X.end() ) ;
		X.erase( unique( X.begin() , X.end() ) , X.end() ) ; 
		int len = X.size() ; 
		double res = 0.0 ;
		for( int i = 0 ; i < num ; i ++ ){
			int l = lower_bound( X.begin() , X.end() , line[i].l ) - X.begin() + 1;
			int r = lower_bound( X.begin() , X.end() , line[i].r ) - X.begin() + 1 - 1 ;
			update( l , r , line[i].cov , 1 , len , 1 ) ;
			res += sum[1] * ( line[i+1].y - line[i].y ) ; 
		}
		printf("%.2lf\n",res);
	}
	return 0 ; 
}

你可能感兴趣的:(线段树)