hdu 1542 Atlantis 线段树矩形面积并+离散化
2016-02-23 10:48
316 查看
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1542
题意:给一些矩形,可能会有重叠,求总的矩形面积
我是看了胡浩的那篇文章,学习一下。
思路:浮点数先要离散化;然后把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用cnt表示该区间下边比上边多几个,sum代表该区间内被覆盖的线段的长度总和
这里线段树的一个结点并非是线段的一个端点,而是该端点和下一个端点间的线段,所以题目中r+1,r-1的地方可以自己好好的琢磨一下
线段树操作:update:区间增减 query:直接取根节点的值
分析:因为线段树每个节点表示的是一个边长,而不是一些点的区间,比如说对于下边【0,1】区间和上边【1,2】区间,如果在更新的时候r不减1,那么1这个点就会被合并,变成【0,0】和【2,2】的边长和,所以在更新的时候r-1.这样的话在求边长总和sum的时候再把1加上去,这样就解决这个问题了。如果读不懂,可以看一下这个图上的解释,在理解一下。http://blog.csdn.net/cen5bin/article/details/7833089
离散化横坐标,对横坐标建树,由于在计算横坐标的时候会去重,得到不同的横坐标k个,因为横坐标数组从0开始,所以要k-1。在更新节点的时候,由于r-1,所以也要对应k-1
题意:给一些矩形,可能会有重叠,求总的矩形面积
我是看了胡浩的那篇文章,学习一下。
思路:浮点数先要离散化;然后把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用cnt表示该区间下边比上边多几个,sum代表该区间内被覆盖的线段的长度总和
这里线段树的一个结点并非是线段的一个端点,而是该端点和下一个端点间的线段,所以题目中r+1,r-1的地方可以自己好好的琢磨一下
线段树操作:update:区间增减 query:直接取根节点的值
分析:因为线段树每个节点表示的是一个边长,而不是一些点的区间,比如说对于下边【0,1】区间和上边【1,2】区间,如果在更新的时候r不减1,那么1这个点就会被合并,变成【0,0】和【2,2】的边长和,所以在更新的时候r-1.这样的话在求边长总和sum的时候再把1加上去,这样就解决这个问题了。如果读不懂,可以看一下这个图上的解释,在理解一下。http://blog.csdn.net/cen5bin/article/details/7833089
离散化横坐标,对横坐标建树,由于在计算横坐标的时候会去重,得到不同的横坐标k个,因为横坐标数组从0开始,所以要k-1。在更新节点的时候,由于r-1,所以也要对应k-1
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int N=205; int cnt[N<<2]; double sum[N<<2],X ; struct edge { double l,r,h; int s; edge(){} edge(double a,double b,double c,int d):l(a),r(b),h(c),s(d){} bool operator<(const edge &cmp)const{ return h<cmp.h; } }e ; void pushUP(int l,int r,int rt) { if(cnt[rt])sum[rt]=X[r+1]-X[l]; //如果是整段都有边,总边长直接左右两个端点之差,这里r+1,是因为在更新的时候r减了1 else if(l==r)sum[rt]=0; //如果两个端点没有覆盖边,那么这个边长不加了总长里。 else sum[rt]=sum[rt<<1]+sum[rt<<1|1]; //否则从子节点得到边长 } void update(int a,int b,int c,int l,int r,int rt) { if(a<=l&&r<=b){ cnt[rt]+=c; pushUP(l,r,rt); return; } int m=(l+r)>>1; if(a<=m)update(a,b,c,lson); if(m<b)update(a,b,c,rson); pushUP(l,r,rt); } int Bin(double key,int n,double X[]) { int l=0,r=n; while(l<=r){ int m=(l+r)>>1; if(X[m]==key)return m; if(X[m]<key)l=m+1; else r=m-1; } return -1; } int main() { int n,cas=0; //freopen("f.txt","r",stdin); while(~scanf("%d",&n)&&n){ int m=0; while(n--){ double a,b,c,d; scanf("%lf%lf%lf%lf",&a,&b,&c,&d); X[m]=a; e[m++]=edge(a,c,b,1); X[m]=c; e[m++]=edge(a,c,d,-1); } sort(X,X+m); sort(e,e+m); int k=1; for(int i=1;i<m;i++){ if(X[i]!=X[i-1])X[k++]=X[i]; } k--; //注意这里 memset(cnt,0,sizeof(cnt)); memset(sum,0,sizeof(sum)); double ans=0; for(int i=0;i<m-1;i++){ int l=Bin(e[i].l,k,X); int r=Bin(e[i].r,k,X)-1; if(l<=r)update(l,r,e[i].s,0,k-1,1); //k和r都减一的原因是一样的。 ans+=sum[1]*(e[i+1].h-e[i].h); } printf("Test case #%d\nTotal explored area: %.2lf\n\n",++cas , ans); } return 0; }
相关文章推荐
- VMware克隆CentOS 6.4后 重新设置eth0
- 浅析若干Java序列化工具
- 点九
- java和android的基础
- Android Studio配置svn时提示需要证书:authentication required的解决方法
- matlab 扩大虚拟内存
- 浅析若干Java序列化工具
- MediaPlayer和AudioTrack播放Audio的区别与联系
- 在Android中实现推送方式的底层原理与推送的知识及相关解决方案
- React.Children
- CSS3 滤镜
- mysql主从异常分析
- label 根据内容text确定控件的大小 分为单行/多行文字
- Ext JS 5.1.0 Grid的deselect事件失效的处理方法
- AOD452场效应管MOS管
- Spring 使用注解方式进行事务管理
- JVM系列之JVM体系(一)
- You have not concluded your merge (MERGE_HEAD exists) git拉取失败
- mm编译 问题
- swift-基本操作02-自增和复合赋值运算符