覆盖的面积 - HDU 1255 扫描线 重复两次的面积
来源:互联网 发布:盘古数据科技有限公司 编辑:程序博客网 时间:2024/06/08 06:37
覆盖的面积
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3841 Accepted Submission(s): 1887
Problem Description
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.
注意:本题的输入数据较多,推荐使用scanf读入数据.
注意:本题的输入数据较多,推荐使用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
题意:计算重复两次以上的面积。
思路:扫描线。tree[o].sum[i]表示节点o所表示的范围内被覆盖次数至少为i的面积有多少,然后向上返回,这样可以降低复杂度。
AC代码如下:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;struct node{ int l,r,lazy; double sum[3];}tree[8010];struct node2{ int l,r,f; double h;}line[2010];bool cmp(node2 a,node2 b){ return a.h<b.h;}double p[2010],sum[2010],x1[1010],y1[1010],x2[1010],y2[1010];int n,m;void build(int o,int l,int r){ tree[o].l=l;tree[o].r=r; tree[o].lazy=0; tree[o].sum[1]=tree[o].sum[2]=0; tree[o].sum[0]=sum[tree[o].r]-sum[tree[o].l-1]; if(l==r) return; int mi=(l+r)/2; build(o<<1,l,mi); build(o<<1|1,mi+1,r);}void solve(int o){ if(tree[o].l==tree[o].r) { int i; for(i=1;i<=min(2,tree[o].lazy);i++) tree[o].sum[i]=tree[o].sum[0]; for(;i<=2;i++) tree[o].sum[i]=0; return; } if(tree[o].lazy>=2) { tree[o].sum[2]=tree[o].sum[1]=tree[o].sum[0]; } else if(tree[o].lazy==1) { tree[o].sum[2]=tree[o<<1].sum[1]+tree[o<<1|1].sum[1]; tree[o].sum[1]=tree[o].sum[0]; } else if(tree[o].lazy==0) { tree[o].sum[2]=tree[o<<1].sum[2]+tree[o<<1|1].sum[2]; tree[o].sum[1]=tree[o<<1].sum[1]+tree[o<<1|1].sum[1]; }}void update(int o,int l,int r,int f){ if(tree[o].l==l && tree[o].r==r && tree[o].lazy+f>=0) { tree[o].lazy+=f; solve(o); return; } int mi=(tree[o].l+tree[o].r)/2; if(r<=mi) update(o<<1,l,r,f); else if(l>mi) update(o<<1|1,l,r,f); else { update(o<<1,l,mi,f); update(o<<1|1,mi+1,r,f); } solve(o);}int find(double f){ int l=0,r=m,mi; while(l<r) { mi=(l+r)/2; if(p[mi]<f) l=mi+1; else r=mi; } return l;}int main(){ int T,t,i,j,k,l,r; double ans; scanf("%d",&T); for(t=1;t<=T;t++) { scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%lf%lf%lf%lf",&x1[i],&y1[i],&x2[i],&y2[i]); p[i*2-1]=x1[i]; p[i*2]=x2[i]; } sort(p+1,p+1+n*2); p[0]=-1; m=-1; for(i=1;i<=n*2;i++) if(p[i]!=p[i-1]) p[++m]=p[i]; for(i=1;i<=m;i++) sum[i]=sum[i-1]+p[i]-p[i-1]; for(i=1;i<=n;i++) { l=find(x1[i])+1;r=find(x2[i]); line[i*2-1].l=l;line[i*2-1].r=r;line[i*2-1].f=1;line[i*2-1].h=y1[i]; line[i*2].l=l;line[i*2].r=r;line[i*2].f=-1;line[i*2].h=y2[i]; } sort(line+1,line+1+n*2,cmp); build(1,1,m); ans=0; for(i=1;i<n*2;i++) { update(1,line[i].l,line[i].r,line[i].f); ans+=tree[1].sum[2]*(line[i+1].h-line[i].h); } printf("%.2f\n",ans); }}
0 0
- 覆盖的面积 - HDU 1255 扫描线 重复两次的面积
- hdu 1255 覆盖的面积 (线段树扫描线 计算两次覆盖的面积)
- hdu 1255 覆盖的面积(线段树&扫描线&重复面积)
- hdu 1255 覆盖的面积 扫描线
- hdu 1255 覆盖的面积(扫描线)
- hdu 1255 覆盖的面积(扫描线)
- hdoj 1255 覆盖的面积【线段树 + 扫描线求重叠两次及以上的面积】
- HDU 1255 覆盖的面积 线段树 扫描线
- 线段树 扫描线 HDU 1255 覆盖的面积
- hdu 1255 覆盖的面积(扫描线)
- HDU-1255 覆盖的面积 线段树 + 扫描线
- hdu 1255 覆盖的面积 线段树扫描线num2
- 【HDU】1255 覆盖的面积 线段树+扫描线
- HDU 1255 覆盖的面积(线段树+扫描线)
- hdu 1255 覆盖的面积 (线段树 扫描线)
- HDU 1255 覆盖的面积(线段树扫描线)
- hdu 1255 覆盖的面积(线段树+扫描线)
- HDU 1255 覆盖的面积 (线段树扫描线)
- 程序大牛必备精品社区
- Linux与Windows远程互访(使用Rdesktop与SSH)
- 制作前端布局的一点点学习经验
- springMVC3学习(七)--Interceptor拦截器
- POJ 2826 An Easy Problem?!
- 覆盖的面积 - HDU 1255 扫描线 重复两次的面积
- C++标准库---advance()&distance()&iter_swap()
- MFC创建桌面快捷方式
- eclipse常用设置
- springMVC3学习(八)--全局的异常处理
- 拿来主义:SQL数据库中触发器的应用案例
- 他人经验
- SQL string类型的数据按int类型排序
- 上的噶是地方撒旦法撒旦法萨德