HDU 1255-覆盖的面积(线段树+扫描线)

来源:互联网 发布:linux网络文件系统鼻祖 编辑:程序博客网 时间:2024/04/29 00:30
C - 覆盖的面积
Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
Submit Status Practice HDU 1255
Appoint description: 

Description

给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 


 

Input

输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000. 

注意:本题的输入数据较多,推荐使用scanf读入数据. 
 

Output

对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数. 
 

Sample Input

251 1 4 21 3 3 72 1.5 5 4.53.5 1.25 7.5 46 3 10 730 0 1 11 0 2 12 0 3 1
 

Sample Output

7.630.00
AC代码:
/*这题一开始是想找题解的,所以当我找了题解后,发现有人一样是不会做这个的,只做了面积并,而且他YY过了所以我也决定要YY过它,所以就没有看题解了。没想到过了一晚时间就让我YY过了,哈哈!!*/#include<iostream>#include<algorithm>#include<cstring>#include<string>#include<cstdio>using namespace std;#define T 10005#define lson (rt<<1)#define rson (rt<<1|1)typedef long long ll;int n;//离散化数组double pos[T];//保存y在x区间的边struct line{double y,x_up,x_down;int flag;bool operator<(const line& a)const{return y<a.y;}line(double _1,double _2,double _3,int _4):y(_1),x_up(_2),x_down(_3),flag(_4){}line(){}}p[T];//线段树数组struct node{int L,R;double len;int mid;int flag;}tree[T];//向上更新void pushup(int rt){if(tree[rt].flag>=2){//完全覆盖区间tree[rt].len = pos[tree[rt].R-1]-pos[tree[rt].L-1];}else if(tree[rt].L+1==tree[rt].R){//叶子节点tree[rt].len = 0;}else//跨越几个区间合并值{tree[rt].len = tree[lson].len+tree[rson].len;/*tree[lson].len = 0,tree[rson].len=0;*/}}/*这题与面积并相像,只是多了一个向下更新,之所以要向下更新是因为,我要的是单个区间都要有值*/void pushdown(int rt){if(tree[rt].flag){tree[lson].flag += tree[rt].flag;tree[rson].flag += tree[rt].flag;tree[rt].flag = 0;}}//建树void build(int rt,int L,int R){tree[rt].L = L;tree[rt].R = R;tree[rt].flag = 0;tree[rt].len = 0;tree[rt].mid = (L+R)>>1;if(L+1!=R){build(lson,L,tree[rt].mid);build(rson,tree[rt].mid,R);}}//更新void update(int rt,int L,int R,int w){/*一开始答案存在偏差,弄了好久发现只要符合范围就返回所以有些区间是将值传递下去了,结果却因为没下去所以漏掉了一些面积,之后一直在调整pushdown函数,结果一直没结果,换成只在区间才返回后就不存在这种情况了。应该可以用懒惰性标记吧*/if(L<=tree[rt].L&&tree[rt].R<=R&&tree[rt].L+1==tree[rt].R){tree[rt].flag+=w;pushup(rt);return;}pushdown(rt);if(R<=tree[rt].mid)update(lson,L,R,w);else if(L>=tree[rt].mid)update(rson,L,R,w);else{update(lson,L,tree[rt].mid,w);update(rson,tree[rt].mid,R,w);}pushup(rt);}int main(){#ifdef zscfreopen("input.txt","r",stdin);#endifint i,c,N;double x1,x2,y1,y2;scanf("%d",&N);while(N--){scanf("%d",&n);c = 0;for(i=0;i<n;++i){scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);pos[c] = x1;p[c++] = line(y1,x1,x2,1);pos[c] = x2;p[c++] = line(y2,x1,x2,-1); }sort(pos,pos+c);int d = unique(pos,pos+c)-pos;build(1,1,d);sort(p,p+c);double ans=0;for(i=0;i<c-1;++i){//因为离散化了,所以要找x的下标int a = lower_bound(pos,pos+d,p[i].x_up)-pos+1;int b = lower_bound(pos,pos+d,p[i].x_down)-pos+1;//更新x区间(a,b)的值update(1,a,b,p[i].flag);ans+=tree[1].len*(p[i+1].y-p[i].y);}printf("%.2lf\n",ans);}return 0;}


0 0
原创粉丝点击