【线段树+扫描线】HDU 1542+1255
来源:互联网 发布:金庸群侠传 lua 源码 编辑:程序博客网 时间:2024/05/16 23:38
简单的说就是从下到上扫描线段,累加记录该线段添加进去之后在总区间的映射有效长度*高度差。
线段树扫描线详解:矩形面积的并:http://www.cnblogs.com/scau20110726/archive/2013/04/12/3016765.html
矩形面积的交:http://www.cnblogs.com/scau20110726/archive/2013/04/14/3020998.html
看了这两篇博客+代码才有所理解。因为扫描的是线段,在线段树中分界点那部分区间可能无法表示,然后就变成了区间左闭右开[l,r),在更新的时候我们可以只更新闭区间即[l,r-1],在记录结果的时候把那个在加上。自己动手画图模拟会有更深的理解。
注意数据的离散化。。。
col[root]枚举到当前边的时候,下方有多少有用线段。(该区间矩形的下边比上边多几条)
即当前结点区间的覆盖情况,不必向下更新,当遇到矩形的上边的时候,直接更新当前结点。sum[root]区间被覆盖的长度
summ[root]区间被重复覆盖的长度/*注意更新*/
HDU 1542 【矩形面积的并】CODE:
#include<stdio.h>#include<string.h>#include<algorithm>#include<queue>#include<stack>#include<math.h>#include<map>#include<iostream>#define INF 0x3f3f3f3f#define lson l,m,root<<1#define rson m+1,r,root<<1|1typedef long long LL;using namespace std;const int mod=998244353;const int maxn=5005;double sum[maxn<<2],X[maxn<<2];int col[maxn<<2];struct node{ double l,r,h; int s; node() {}; node(double a,double b,double c,int d) { l=a,r=b,h=c; s=d; } bool operator <(const node &cmp)const { return h<cmp.h; }}ss[maxn<<2];void pushup(int l,int r,int root){ if(col[root]) sum[root]=X[r+1]-X[l];//********* else if(l==r) sum[root]=0; else sum[root]=sum[root<<1]+sum[root<<1|1];}void update(int L,int R,int c,int l,int r,int root){ if(L<=l&&r<=R) { col[root]+=c; pushup(l,r,root); return; } int m=(l+r)>>1; if(L<=m) update(L,R,c,lson); if(R>m) update(L,R,c,rson); pushup(l,r,root);}int main(){ int n,T=0; while(~scanf("%d",&n)&&n) { int m=0,k=1; double a,b,c,d; for(int i=0;i<n;i++) { scanf("%lf%lf%lf%lf",&a,&b,&c,&d); X[m]=a; ss[m++]=node(a,c,b,1); X[m]=c; ss[m++]=node(a,c,d,-1); } sort(X,X+m); sort(ss,ss+m); for(int i=1;i<m;i++) { if(X[i]!=X[i-1]) X[k++]=X[i]; } double ans=0; memset(col,0,sizeof(col)); memset(sum,0,sizeof(sum)); for(int i=0;i<m-1;i++) { int l=lower_bound(X,X+k,ss[i].l)-X; int r=lower_bound(X,X+k,ss[i].r)-X-1;//****** if(l<=r) update(l,r,ss[i].s,0,k-1,1); ans+=sum[1]*(ss[i+1].h-ss[i].h); } printf("Test case #%d\nTotal explored area: %.2lf\n\n",++T,ans);//注意格式 }}
HDU 1225【矩形面积的交】 CODE:
summ[]数组的更新:1、col[root]>1,即该区间全部被覆盖了两次及两次以上,长度就是该区间的长度;
2、l==r最底层的叶子节点,无论覆盖没覆盖,都为0;
3、col[root]=1,左右子节点覆盖一次及一次以上的和(因为col[]没有向下更新,如果子区间有被 覆盖的,则就是被重复覆盖的);
4、其他,左右子节点覆盖两次及两次以上的和。
#include<stdio.h>#include<string.h>#include<algorithm>#include<queue>#include<stack>#include<math.h>#include<map>#include<iostream>#define INF 0x3f3f3f3f#define lson l,m,root<<1#define rson m+1,r,root<<1|1typedef long long LL;using namespace std;const int mod=998244353;const int maxn=5005;double sum[maxn<<2],X[maxn<<2];double summ[maxn<<2];int col[maxn<<2];struct node{ double l,r,h; int s; node() {}; node(double a,double b,double c,int d) { l=a,r=b,h=c; s=d; } bool operator <(const node &cmp)const { return h<cmp.h; }} ss[maxn<<2];void pushup(int l,int r,int root){ if(col[root]) sum[root]=X[r+1]-X[l]; else if(l==r) sum[root]=0; else sum[root]=sum[root<<1]+sum[root<<1|1]; if(col[root]>1) summ[root]=X[r+1]-X[l]; else if(l==r) summ[root]=0; else if(col[root]==1) summ[root]=sum[root<<1]+sum[root<<1|1]; else summ[root]=summ[root<<1]+summ[root<<1|1];}void update(int L,int R,int c,int l,int r,int root){ if(L<=l&&r<=R) { col[root]+=c; pushup(l,r,root); return; } int m=(l+r)>>1; if(L<=m) update(L,R,c,lson); if(R>m) update(L,R,c,rson); pushup(l,r,root);}int main(){ int n,t; scanf("%d",&t); while(t--) { scanf("%d",&n); int m=0,k=1; double a,b,c,d; for(int i=0; i<n; i++) { scanf("%lf%lf%lf%lf",&a,&b,&c,&d); X[m]=a; ss[m++]=node(a,c,b,1); X[m]=c; ss[m++]=node(a,c,d,-1); } sort(X,X+m); sort(ss,ss+m); for(int i=1; i<m; i++) { if(X[i]!=X[i-1]) X[k++]=X[i]; } double ans=0; memset(col,0,sizeof(col)); memset(sum,0,sizeof(sum)); memset(summ,0,sizeof(summ)); for(int i=0; i<m-1; i++) { int l=lower_bound(X,X+k,ss[i].l)-X; int r=lower_bound(X,X+k,ss[i].r)-X-1; if(l<=r) update(l,r,ss[i].s,0,k-1,1); // cout<<l<<" "<<r<<"---"<<sum[1]<<endl; ans+=summ[1]*(ss[i+1].h-ss[i].h); } printf("%.2lf\n",ans); }}
- 【线段树+扫描线】HDU 1542+1255
- HDU 1255 线段树+扫描线
- hdu 1542 线段树扫描线
- hdu 1542 Atlantis 线段树扫描线
- HDU 1542 Atlantis(线段树:扫描线)
- 【HDU】1542 Atlantis 线段树+扫描线
- HDU 1542 Atlantis(线段树扫描线)
- HDU - 1542 (扫描线+线段树优化)
- hdu 1542 线段树+扫描线
- hdu 1542 Atlantis(线段树+扫描线)
- HDU-1542(线段树+扫描线)
- hdu 1542 Atlantis 线段树 + 扫描线
- HDU 1542 Atlantis 线段树+扫描线
- HDU - 1542 Atlantis(线段树 扫描线)
- HDU 1542 Atlantis 【线段树+扫描线】
- HDU 1542 Atlantis 线段树+扫描线
- hdu 1542 扫描线+线段树
- HDU 1542 HDU 1225 (线段树扫描线)
- WebStorage(1)__<本地数据,离线缓存>
- 【真题】网易有道2017内推编程题 模拟洗牌
- 业余时间决定了你的人生
- MySQL server has gone away 问题分析
- Redis在Windows上编译
- 【线段树+扫描线】HDU 1542+1255
- mobienet
- Leetcode500. Keyboard Row
- java使double保留两位小数的多方法 java保留两位小数
- Spring Data JPA使用复合主键
- AlexNet网络结构
- mysql的主从复制与读写分离
- 从本地读数据并转为Map格式
- 1.1 关于ARM中重定位:位置有关码和位置无关码及运行地址和链接地址