hdu 1255 覆盖的面积(线段树&扫描线&重复面积)
来源:互联网 发布:手机淘宝订单号查询 编辑:程序博客网 时间:2024/06/05 03:35
覆盖的面积
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3375 Accepted Submission(s): 1645
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
Author
Ignatius.L & weigang Lee
Recommend
Ignatius.L | We have carefully selected several similar problems for you: 1542 1828 1823 1541 3333
题意:
中文题目就不解释了。题目有点问题。应该是左下角和右上角坐标。
思路:
线段树加扫描线。但是这题算的不是面积并而是被重复覆盖的面积。可是值学过面积并。于是只能YY咯。没想到还真YY出来了。感动ing....。具体做法就是在线段树结点新增一个信息.relen.len表示被覆盖一次的长度。而relen表示被重复覆盖的长度。但是怎么维护这个新加入的信息呢。当当前区间被覆盖超过一次时。毫无疑问len和relen都是当前区间的长度。当当前区间被覆盖一次时len肯定是区间的长度。这个relen肯定就是左右儿子的len和了。因为由于整个区间被覆盖一次。加上儿子区间以前被覆盖的肯定就覆盖多次了。满足条件。当当前区间被覆盖0次时这时relen=儿子的relen和了。其它的就好求面积并一样了。
详细见代码:
#include<algorithm>#include<iostream>#include<string.h>#include<stdio.h>using namespace std;const int INF=0x3f3f3f3f;const int maxn=2510;#define lson L,mid,ls#define rson mid+1,R,rsint n,m;int cov[maxn<<2];double len[maxn<<2],relen[maxn<<2],H[2500];struct node{ double x1,x2,h; int v; node(double a=0,double b=0,double c=0,int d=0):x1(a),x2(b),h(c),v(d){}} seg[maxn];bool cmp(node a,node b){ return a.h<b.h;}void init(){ sort(H,H+m); m=unique(H,H+m)-H;}int Hash(double x){ return lower_bound(H,H+m,x)-H;}void PushUp(int L,int R,int rt){ if(cov[rt]>1)//有标记肯定整块覆盖了 len[rt]=relen[rt]=H[R+1]-H[L]; else if(cov[rt]==1) { len[rt]=H[R+1]-H[L],relen[rt]=0; if(L!=R) relen[rt]=len[rt<<1]+len[rt<<1|1]; } else if(L==R)//没有左右儿子了。 len[rt]=relen[rt]=0; else//没有整块覆盖但是被部分覆盖了 len[rt]=len[rt<<1]+len[rt<<1|1],relen[rt]=relen[rt<<1]+relen[rt<<1|1];}void update(int L,int R,int rt,int l,int r,int d){ if(l<=L&&R<=r) { cov[rt]+=d; PushUp(L,R,rt); return; } int mid=(L+R)>>1,ls=rt<<1,rs=ls|1; if(l<=mid) update(lson,l,r,d); if(r>mid) update(rson,l,r,d); PushUp(L,R,rt);}int main(){ int t,i,ptr; double x1,x2,y1,y2,ans; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i=ptr=0;i<n;i++) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); H[ptr]=x1; seg[ptr++]=node(x1,x2,y1,1); H[ptr]=x2; seg[ptr++]=node(x1,x2,y2,-1); } m=ptr,ans=0; init(); sort(seg,seg+ptr,cmp); memset(len,0,sizeof len); memset(relen,0,sizeof relen); memset(cov,0,sizeof cov); for(i=0,ptr--;i<ptr;i++) { update(0,m-1,1,Hash(seg[i].x1),Hash(seg[i].x2)-1,seg[i].v);//m个结点m-1条线段 ans+=(seg[i+1].h-seg[i].h)*relen[1]; } printf("%.2lf\n",ans); } return 0;}
1 0
- hdu 1255 覆盖的面积(线段树&扫描线&重复面积)
- HDU 1255 覆盖的面积 线段树 扫描线
- 线段树 扫描线 HDU 1255 覆盖的面积
- HDU-1255 覆盖的面积 线段树 + 扫描线
- hdu 1255 覆盖的面积 线段树扫描线num2
- 【HDU】1255 覆盖的面积 线段树+扫描线
- HDU 1255 覆盖的面积(线段树+扫描线)
- hdu 1255 覆盖的面积 (线段树 扫描线)
- HDU 1255 覆盖的面积(线段树扫描线)
- hdu 1255 覆盖的面积(线段树+扫描线)
- HDU 1255 覆盖的面积 (线段树扫描线)
- HDU - 1255 覆盖的面积(线段树 扫描线)
- HDU 1255 覆盖的面积 线段树+扫描线
- hdu-1255 覆盖的面积(扫描线+线段树)
- HDU 1255-覆盖的面积(线段树+扫描线)
- hdu 1255 覆盖的面积(线段树|扫描线)
- HDU 1255 覆盖的面积(线段树扫描线)
- hdu 1255 覆盖的面积(线段树+扫描线)
- android自定义View-垂直滚动的TextView
- JAVA的eaquls和“==”字符串比较
- OpenCV学习笔记5 OpenCV核心模块与核心功能Core Module & Core Functionality(四)
- 怎么恢复被误删硬盘文件
- java4android36集到38集,线程
- hdu 1255 覆盖的面积(线段树&扫描线&重复面积)
- Hibernate学习笔记
- 01背包、完全背包、多重背包 总结小讲
- FZU1759Super A^B mod C(快速幂取模) 公式
- 两台服务器同步数据 rsync
- 如何恢复数码相机存储卡上已被删除的照片,数码相机存储卡照片数据恢复教程
- 虚拟化、大数据、云计算、物联网、移动互联网以及传统互联网之间的关系
- TOMCAT内存溢出及大小调整
- 使用SDL播放YUV图像数据