POJ 1151 Atlantis
来源:互联网 发布:顶级定制晚礼服 知乎 编辑:程序博客网 时间:2024/05/16 13:46
题解在注释中,每个函数都有解释。
//// main.cpp// Richard//// Created by 邵金杰 on 16/7/25.// Copyright © 2016年 邵金杰. All rights reserved.//#include<iostream>#include<cstdio>#include<algorithm>using namespace std;//存放纵轴的struct line{ double x,y1,y2; bool bleft;}line[210];double y[210];struct node{ int L,R; node *pleft,*pright; int cover; double len;}tree[900];int nNodetree=0;bool operator < (const struct line &l1,const struct line &l2){ return l1.x<l2.x;}template<class F,class T>F bin_search(F s,F e,T val){ F L=s; F R=e-1; while(L<=R) { F mid=L+(R-L)/2; if(!((*mid>val)||(*mid<val))) return mid; else if(*mid>val) R=mid-1; else L=mid+1; } return e;}int mid(node *p){ return (p->L+p->R)/2;}//建树void Buildtree(node *p,int L,int R){ p->L=L; p->R=R; p->len=0; p->cover=0; if(L==R) return ; nNodetree++; p->pleft=tree+nNodetree; nNodetree++; p->pright=tree+nNodetree; Buildtree(p->pleft,L,mid(p)); Buildtree(p->pright,mid(p)+1,R);}//如果区间刚好在所插入范围内,那么直接把p->len=y[R+1]-y[L],为什么要R+1,因为L和R都代表区间,所以这个区间的最上面的坐标为y[L],最下面的轴是y[R+1],相减就是矩形在该区间内所占的高,前提是完全覆盖该区间的,所以p->cover++,接下来就是区间没有完美配对的情况了,那么区间会分解,这都是套路不说了,最后那句话是更新母节点的(并非是根结点),如果该结点所代表的区间不是完全被覆盖的,那么所覆盖的矩形的高就是p->len=p->pleft->len+p->pright->len;(这句话非常关键,否则根结点无法及时更新的话,会导致该条纵轴与下一条纵轴之间的矩形面积为0,导致最后答案错误);void Insert(node *p,int L,int R){ if(p->L==L&&p->R==R) { p->len=y[R+1]-y[L]; p->cover++; return ; } if(R<=mid(p)) Insert(p->pleft,L,R); else if(L>mid(p)) Insert(p->pright,L,R); else{ Insert(p->pleft,L,mid(p)); Insert(p->pright,mid(p)+1,R); } if(p->cover==0) p->len=p->pleft->len+p->pright->len;}//与Insert类似,如果完美配对,那么矩形之前是完美覆盖该区间的,那么现在矩形到右边的轴了,就不再覆盖了,所以p->cover--,当p->cover==0时,代表该区间已经没有完全覆盖的矩形了,如果时单个区间,那么p->len=0,如果是多个单区间组合起来的组合区间,那么p->len=p->pleft->len+p->pright->len;(因为可能有不完美覆盖该区间的矩形,但是有一部分在该区间内),接下来是区间不配对时的分解区间,最后一个if的意思也是跟新母节点,知道跟新根结点,理由在Insert函数中已经阐述过了,类似。void Delete(node *p,int L,int R){ if(p->L==L&&p->R==R) { p->cover--; if(p->cover==0){ if(p->L==p->R) p->len=0; else p->len=p->pleft->len+p->pright->len; } return ; } if(R<=mid(p)) Delete(p->pleft,L,R); else if(L>mid(p)) Delete(p->pright,L,R); else{ Delete(p->pleft,L,mid(p)); Delete(p->pright,mid(p)+1,R); } if(p->cover==0) p->len=p->pleft->len+p->pright->len;}int main(){ int n,kase=0,yc,lc; double x1,x2,y1,y2; double area; while(scanf("%d",&n)&&n) { area=0; yc=0,lc=0; for(int i=0;i<n;i++) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); y[yc++]=y1; y[yc++]=y2; line[lc].x=x1; line[lc].y1=y1; line[lc].y2=y2; line[lc].bleft=true; lc++; line[lc].x=x2; line[lc].y1=y1; line[lc].y2=y2; line[lc].bleft=false; lc++; } sort(y,y+yc);//整理横轴,然后分解区间 yc=(int)(unique(y,y+yc)-y);//一共有yc条横轴 Buildtree(tree,0,yc-1-1);//yc-1是区间数,因为区间开始是0,所以结束是yc-1-1; sort(line,line+lc); for(int i=0;i<lc-1;i++) { int L=(int)(bin_search(y,y+yc,line[i].y1)-y); int R=(int)(bin_search(y,y+yc,line[i].y2)-y);//寻找该矩形的区间 if(line[i].bleft) Insert(tree,L,R-1);//因为找到的是线的位置,但是插入是对区间操作的,所以区间是从L~R-1的 else Delete(tree,L,R-1); area+=tree[0].len*(line[i+1].x-line[i].x);//tree[0]代表的是在line[i].x与line[i+1].x之间举行的宽是多少,相乘之后就代表了在line[i].x~line[i+1].x之间的矩形面积,因为有lc-1个范围,所以每次area都要更新。 } printf("Test case #%d\n",++kase); printf("Total explored area: %.2f \n",area); printf("\n"); } return 0;}
0 0
- POJ 1151 Atlantis
- poj 1151 Atlantis
- poj 1151 Atlantis
- poj 1151 Atlantis
- poj 1151 Atlantis
- POJ 1151 Atlantis
- poj 1151 Atlantis
- POJ 1151 Atlantis
- NYOJ186 Atlantis & POJ 1151
- POJ-1151-Atlantis
- POJ 1151: Atlantis
- poj 1151 Atlantis
- poj 1151 Atlantis
- POJ 1151 Atlantis
- poj 1151 Atlantis
- poj-1151-Atlantis
- POJ 1151 Atlantis
- POJ 1151 Atlantis
- JavaScript实现点击(按钮)实现添加css样式
- Volley 的 小实例
- 文档说明
- Length of Last Word
- 设计模式学习笔记--设计模式概述
- POJ 1151 Atlantis
- u3d fbx动画模型生成Animator Controller和Prefab工具脚本
- Python 之 日志logging 之 2
- java基础Day04
- 四大组件之其三
- 排序算法(1)插入排序的算法分析
- solr6.1 安装,开发demo
- 如何在yii引入sphinx
- lua string库