HDU 1255 覆盖的面积

/*

做这题的时候是参考别人的程序

现在拿出来回顾下

好好理解一下这题的思路

第一,这题需要离散化

第二,计算矩形并的面积 当某一条线段被覆盖两次或两次以上 计算一次面积 具体的画个图比较明了

第三,也是最重要的,线段数once, more的更新, 当时没有掌握到线段数的精髓 也是迷迷糊糊的,

现在回来想想,once more 是第一类信息 表示当前区间的性质

所有递归回来的时候 由递推关系更新once more 而more 又是由once 推出来的 

*/

#include <stdio.h>



#include <stdlib.h>



#include <math.h>



#define EPS 1e-8



#define L(x) ((x) << 1)



#define R(x) ((x) << 1 | 1)







const int MAXN = 2222;



struct Line



{



	double x,y1,y2;



	int flag;



};



bool equal(double a, double b){



	if( fabs(a - b) <= EPS)



		return true;



	return false;



}



int doubleCmp(const void *a, const void *b){



	return *(double*)a - *(double*)b > 0 ? 1 : -1;



}



int cmp(const void *a, const void *b){



	Line *l1 = (Line*)a;



	Line *l2 = (Line*)b;



	if( equal(l1 -> x, l2 -> x)){



		return l1 -> flag - l2 -> flag;



	}



	return (l1 -> x) - (l2 -> x) > 0 ? 1 : -1;	//浮点数比较大小 要注意



}







struct segTree



{



	int l,r;	



	int cov;		//覆盖次数



	double once, more;	//覆盖一次的长度和覆盖两次的长度



};







Line line[2 * MAXN];



segTree tree[MAXN * 4];		//空间



double pointy[2 * MAXN];







void bulid(int left, int right, int t){



	tree[t].l = left;



	tree[t].r = right;



	tree[t].cov = 0;



	tree[t].once = tree[t].more = 0.0;



	tree[L(t)].cov = 0;



	tree[L(t)].once = tree[L(t)].more = 0.0;



	tree[R(t)].cov = 0;



	tree[R(t)].once = tree[R(t)].more = 0.0;



	if( right - left == 1)



		return;



	int mid = (left + right) >> 1;



	



	bulid(left, mid, L(t));



	bulid(mid, right, R(t));



}











int bsearch(int l, int r, double temp){



	



	while(l <= r){



		int mid = ( l + r ) >> 1; 



		if( equal(pointy[mid], temp)){



			return mid;



		} else if( pointy[mid] > temp ){



			r = mid - 1;



		} else if(pointy[mid] < temp){



			l = mid + 1;



		}



	}



	return -1;



}



void rr(int t,int l, int r){

	//分情况讨论



	if(tree[t].cov > 1){	//覆盖多次



		tree[t].once = 0;



		tree[t].more = pointy[r] - pointy[l];



	} else if( tree[t].cov == 1){	//覆盖一次 则覆盖两次的长度为儿子覆盖一次和两次的长度之和 覆盖一次的长度则为总长度减去覆盖多次的长度 因为不可能存在没被覆盖的区域



		tree[t].more = tree[L(t)].more + tree[R(t)].more 



			+ tree[L(t)].once + tree[R(t)].once;



		tree[t].once = pointy[r] - pointy[l] - tree[t].more;



	} else {	// == 0 没被覆盖



		if( r - l == 1){			//叶子



			tree[t].once = tree[t].more = 0;



		} else {				//由左右孩子的once more 更新自己的once more



			tree[t].once = tree[L(t)].once + tree[R(t)].once;



			tree[t].more = tree[L(t)].more + tree[R(t)].more;



		}



	}



}







void update(int l, int r, int t, int flag){

	/*这递归不是我的风格 哈哈 真是copy啊*/



	if( l >= tree[t].r || r <= tree[t].l)	//不在这个区间 



		return;



	if( l <= tree[t].l && r >= tree[t].r){ 	//包含这个区间



		tree[t].cov += flag;



		rr(t,tree[t].l,tree[t].r);	//如果覆盖区间 则rr once more 然后直接返回 



		return; 			//important	



	}



	update(l, r, L(t), flag);



	update(l, r, R(t), flag);



	rr(t,tree[t].l,tree[t].r);		//rr函数更新节点的once more



}











int main(){



	int t, n, i, j;



	double x1, x2, y1, y2;



	scanf("%d",&t);



	while( t-- ){



		scanf("%d",&n);



		j = 1;



		for(i = 1; i <= n; i++){



			scanf("%lf%lf%lf%lf",&x1, &y1, &x2, &y2);



			line[j].x = x1;



			line[j].y1 = y1;



			line[j].y2 = y2;



			line[j].flag = 1;



			pointy[j] = y1;



			j++;



			line[j].x = x2;



			line[j].y1 = y1;



			line[j].y2 = y2;



			line[j].flag = -1;



			pointy[j] = y2;



			j++;



		}



		qsort(pointy + 1, 2 * n , sizeof(pointy[0]), doubleCmp);



		qsort(line + 1, 2 * n , sizeof(line[0]), cmp);



		//离散化



		int size = 1;



		for(i = 2; i <= 2 * n; i++){



			if(!equal(pointy[i] , pointy[i - 1])){



				pointy[++size] = pointy[i];



			}



		}



		bulid(1, size, 1);



		double ans = 0.0;



		for(i = 1; i <= 2 * n; i++){



			if(i != 1){



				ans += (line[i].x - line[i - 1].x) * tree[1].more;



			}



			int y1 = bsearch(1, size, line[i].y1);



			int y2 = bsearch(1, size, line[i].y2);



			update(y1, y2, 1, line[i].flag);



		}



		printf("%.2lf\n",ans);



	}



	return 0;



}


你可能感兴趣的:(HDU)