HDU-1542:Atlantis(扫描线模板题)
来源:互联网 发布:笔记本风扇转速软件 编辑:程序博客网 时间:2024/06/06 04:44
题目链接:点击打开链接
题目大意:
题目给你一些矩形的左下角坐标和右上角坐标,然后计算形成的新图形的面积。中间重叠的部分算作一部分。
题意解析:
要用到线段树扫描线的知识,从坐标系的下面往上面一次扫,每次维护当前高度的有效线段长。然后就可以通过高度差还有效线段长计算有效面积。
代码:
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<queue>#include<vector>using namespace std;struct node //记录线段左端点右端点和当前线段高度{ double l,r,h; int flag; //记录当前线段为上位边和下位边 bool operator<(const node &b) //通过线段高度对线段排序 { return h<b.h; }}nodes[500000];struct tree{ int l,r,mid; int cnt; //下位边减上位边的数 double sum; //本节点控制区域内cnt不为0的总长度}t[500000];int n;double x[500000];void pushdown(int rt) //从上到下维护{ if(t[rt].cnt!=-1) { t[rt<<1].cnt=t[rt<<1|1].cnt=t[rt].cnt; if(t[rt].cnt) { t[rt<<1].sum=x[t[rt].mid+1]-x[t[rt].l]; t[rt<<1|1].sum=x[t[rt].r+1]-x[t[rt].mid+1]; } else { t[rt<<1].sum=0; t[rt<<1|1].sum=0; } }}void pushup(int rt) //自上而下维护,cnt=-1代表当前区间左右儿子的上下位边数不同{ if(t[rt<<1].cnt==-1||t[rt<<1|1].cnt==-1) t[rt].cnt=-1; else if(t[rt<<1].cnt!=t[rt<<1|1].cnt) t[rt].cnt=-1; else t[rt].cnt=t[rt<<1].cnt; t[rt].sum=t[rt<<1].sum+t[rt<<1|1].sum; //printf("----%lf %d %lf %d\n",t[rt<<1].sum,t[rt<<1].l,t[rt<<1|1].sum,t[rt<<1|1].l);}void build(int l,int r,int rt){ if(l==r) { t[rt].l=t[rt].r=l; t[rt].mid=(t[rt].l+t[rt].r)/2; t[rt].cnt=0; t[rt].sum=0.0; return ; } int mid=(l+r)/2; t[rt].l=l; t[rt].r=r; t[rt].mid=mid; t[rt].cnt=0; t[rt].sum=0.0; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); pushup(rt);}void update(int l,int r,int flag,int rt) //更新结果{ if(t[rt].l>=l&&t[rt].r<=r) { if(t[rt].cnt!=-1) { t[rt].cnt=t[rt].cnt+flag; if(t[rt].cnt) t[rt].sum=x[t[rt].r+1]-x[t[rt].l]; else t[rt].sum=0; return ; } } pushdown(rt); if(l<=t[rt].mid) update(l,r,flag,rt<<1); if(r>t[rt].mid) update(l,r,flag,rt<<1|1); pushup(rt);}int bin(double key,int n,double d[]){ int l=1,r=n; while(l<=r) { int m=(l+r)/2; if(d[m]==key) return m; else if(d[m]>key) r=m-1; else l=m+1; } return -1;}int main(){ int kase=0; while(scanf("%d",&n)!=EOF) { int gg=0; if(n==0) break; for(int i=0;i<n;i++) { double x1,y1,x2,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); x[++gg]=x1; nodes[gg].l=x1; nodes[gg].r=x2; nodes[gg].h=y1; nodes[gg].flag=1; x[++gg]=x2; nodes[gg].l=x1; nodes[gg].r=x2; nodes[gg].h=y2; nodes[gg].flag=-1; } sort(x+1,x+gg+1); sort(nodes+1,nodes+gg+1); int k=1; for(int i=2;i<=gg;i++) { if(x[i-1]!=x[i]) x[++k]=x[i]; } build(1,k-1,1); //用每个节点代表一段区间 double ans=0.0; for(int i=1;i<gg;i++) { int l=bin(nodes[i].l,k,x); int r=bin(nodes[i].r,k,x)-1; if(l<=r) update(l,r,nodes[i].flag,1); //printf("%lf\n",t[1].sum); ans=ans+t[1].sum*(nodes[i+1].h-nodes[i].h); } printf("Test case #%d\nTotal explored area: %.2lf\n\n",++kase,ans); }}
阅读全文
0 0
- HDU-1542:Atlantis(扫描线模板题)
- Atlantis - HDU 1542 扫描线
- hdu 1542 Atlantis(扫描线)
- hdu 1542 Atlantis(扫描线)
- HDU 1542 Atlantis 扫描线
- HDU 1542 Atlantis(线段树+离散化+扫描线)
- hdu 1542 Atlantis(线段树,扫描线)
- hdu 1542 Atlantis (线段树+离散化+扫描线)
- HDU 1542 - Atlantis (线段树 扫描线)
- HDU 1542 && POJ 1151 Atlantis(线段树+扫描线)
- hdu 1542 Atlantis (扫描线方法 o(n^2))
- HDU 1542 Atlantis(线扫描求面积)
- poj 1151 hdu 1542 atlantis (线段树+扫描线)
- HDU 1542 Atlantis(线段树扫描线,面积并)
- HDU 1542 Atlantis (线段树 +离散化+ 扫描线)
- HDU 1542-Atlantis(线段树+扫描线)
- HDU - 1542 Atlantis(线段树扫描线基础)
- poj 1151 & hdu 1542 Atlantis(线段树,扫描线)
- mac 连接上l2tp但是无法访问公网
- 正则表达式
- 单片机第二次实验
- LVS负载均衡架构原理
- java内部类详解
- HDU-1542:Atlantis(扫描线模板题)
- POJ 2100 Graveyard Design
- 使用js解析json数据
- 【解题报告】小胖守皇宫
- Stereo Matching文献笔记之(十):经典算法Semi-Global Matching(SGM)之碉堡的动态规划~
- 关于inodes占用100%的问题及解决方法
- 蒙特卡洛方法(Monte Carlo Method)
- java枚举类详解
- python3 爬虫环境准备 (一)