覆盖的面积
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3553 Accepted Submission(s): 1743
Problem Description
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.
注意:本题的输入数据较多,推荐使用scanf读入数据.
注意:本题的输入数据较多,推荐使用scanf读入数据.
Output
对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
Sample Input
2 5 1 1 4 2 1 3 3 7 2 1.5 5 4.5 3.5 1.25 7.5 4 6 3 10 7 3 0 0 1 1 1 0 2 1 2 0 3 1
Sample Output
7.63 0.00
#include<iostream> #include<cstdio> #include<algorithm> #define Max 10005 using namespace std; struct line{ double x, y1, y2; int flag; }x_line[Max]; struct node{ int l, r, flag; double x, f; }tree[Max]; double point[Max]; int n, m, xm; int cmp(double a,double b) { return a<b; } bool comp(line a,line b) { return a.x<b.x; } void Build(int l,int r,int k) { int m; tree[k].l = l; tree[k].r = r; tree[k].flag = 0; tree[k].x = 0.0; tree[k].f = 0.0; if(l+1 == r) return; m = (l+r)>>1; Build(l,m,k+k); Build(m,r,k+k+1); } void Myscanf() { m = 1; double x1,x2,y1,y2; scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); point[m] = y1; x_line[m].x = x1; x_line[m].y1 = y1; x_line[m].flag = 1; x_line[m++].y2 = y2; point[m] = y2; x_line[m].x = x2; x_line[m].y1 = y1; x_line[m].flag = -1; x_line[m++].y2 = y2; } } void Point_Do() { int mi = 0; sort(point+1,point+m,cmp); sort(x_line+1,x_line+m,comp); xm = m; for(int i=1; i<m; i++) { if(point[i]!=point[mi]) point[++mi] = point[i]; //去重 } m = mi; } int Bin(double xi) { int l = 1, r = m; int mi; while(l<=r) { mi = (l+r)>>1; if(xi == point[mi]) return mi; if(xi > point[mi]) l = mi+1; else r = mi-1; } return -1; } void update(int l, int r, int k, line cur) { if(tree[k].l==tree[k].r-1) { if(tree[k].flag == 1 && cur.flag == 1) tree[k].f = cur.x; else if(tree[k].flag==2 && cur.flag==-1){ tree[k].x +=( cur.x - tree[k].f ); tree[k].f = 0.0; } tree[k].flag+=cur.flag; return; } int mi = (tree[k].l+tree[k].r)>>1; if(l>=mi) update(l,r,k+k+1,cur); else if(r<=mi) update(l,r,k+k,cur); else{ update(l,mi,k+k,cur); update(mi,r,k+k+1,cur); } return; } double query(int k) { if(tree[k].l + 1==tree[k].r) return (point[tree[k].r]-point[tree[k].l])*tree[k].x; return query(k+k) + query(k+k+1); } int Ans() { for(int i=1;i<xm;i++) { int x = Bin(x_line[i].y1); int y = Bin(x_line[i].y2); update(x,y,1,x_line[i]); } } int main() { int Case; scanf("%d",&Case); while(Case--) { memset(tree,0,sizeof(tree)); memset(point,-1,sizeof(point)); memset(x_line,0,sizeof(x_line)); Myscanf(); Point_Do(); Build(1,m,1); Ans(); printf("%.2lf ",query(1)); } return 0; }
主要思路就是将y轴离散为线段树,然后,将x轴转换为状态,其实也可以x为线段树,y为状态的
版权声明:本文为博主原创文章,未经博主允许不得转载。