标签:UI blog math 清空 ons print cal ant pac
2 10 10 20 20 15 15 25 25.5 0Sample Output
Test case #1 Total explored area: 180.00
就是给定你2若干个矩形,求覆盖的面积。
看数据范围,就要用离散化来做,我们可以使用扫描线,沿着x轴扫过去,将每一个x坐标所对应的y的上下界用线段树表示出来,当一个矩形入边加入的时候就+1,否则就-1,然后算出面积就可以了。
具体看代码,我写了一些较为详细的注释。
#pragma GCC optimize("O2") #include<iostream> #include<cmath> #include<cstdlib> #include<cstdio> #include<algorithm> #include<cstring> #include<string> #include<ctype.h> #define ls (rt<<1) #define rs (rt<<1|1) #define mid (l+(r-l)/2) #define maxn 500 #define LL long long using namespace std; struct TREE{int l,r,c;double cnt,lf,rf;}tr[maxn*4];//l,r存线段树的下标,c存+1-1,就是这颗扫描线扫过的矩形的数量,cnt存答案,也就是一段区间,lf,rf为区间的左右界 struct Line{double x,y1,y2;int c;}line[maxn]; int m=0,n; double y[maxn]; bool cmp(Line a,Line b){return a.x<b.x;} void build(int l,int r,int rt)//离散化,坐标一一对应 { tr[rt].l=l;tr[rt].r=r; tr[rt].cnt=tr[rt].c=0; tr[rt].lf=y[l],tr[rt].rf=y[r]; if(l+1==r) return;//左闭右开的区间 build(l,mid,ls); build(mid,r,rs);//同上所以不是mid+1 }//说一下区间为什么要 左闭右开,因为这样在计算面积的时候就不用+1-1,就不会出现细节上的错误 void getlen(int rt) { if(tr[rt].c) { tr[rt].cnt=tr[rt].rf-tr[rt].lf; // tr[rt].c=0;//注意这里不能清空,应该在下一条出边加入的时候才能清空 return ; } if(tr[rt].l+1==tr[rt].r) tr[rt].cnt=0;//如果是一个节点而不是区间 else tr[rt].cnt=tr[ls].cnt+tr[rs].cnt; return ; } void update(int rt,Line e) { if(e.y1==tr[rt].lf&&e.y2==tr[rt].rf) { tr[rt].c+=e.c; getlen(rt); return ; } if(e.y2<=tr[ls].rf) update(ls,e);//左儿子和右儿子要分开计算 else if(e.y1>=tr[rs].lf) update(rs,e); else { Line tmp=e; tmp.y2=tr[ls].rf; update(ls,tmp); tmp=e; tmp.y1=tr[rs].lf; update(rs,tmp); } getlen(rt); } void input() { double x1,x2,y1,y2; for(int i=1;i<=n;i++) { cin>>x1>>y1>>x2>>y2; line[++m].x=x1;line[m].y1=y1;line[m].y2=y2;line[m].c=1; y[m]=y1; line[++m].x=x2;line[m].y1=y1;line[m].y2=y2;line[m].c=-1; y[m]=y2; } sort(line+1,line+m+1,cmp); sort(y+1,y+m+1);//坐标离散化 } void init()//记得初始化 { memset(tr,0,sizeof(tr)); m=0; memset(line,0,sizeof(line)); memset(y,0,sizeof(y)); } int main() { int kase=0; while(cin>>n&&n) { init(); input(); build(1,m,1); update(1,line[1]);//先加入第一条线 double ans=0; for(int i=2;i<=m;i++) { ans+=tr[1].cnt*(line[i].x-line[i-1].x);//标准的面积计算公式 update(1,line[i]); } printf("Test case #%d\n", ++kase); printf("Total explored area: %.2lf\n\n",ans); } return 0; } /* 2 1 1 3 3 2 2 4 4 */
标签:UI blog math 清空 ons print cal ant pac
原文地址:http://www.cnblogs.com/foreverpiano/p/7073112.html