P - Atlantis (线段树+扫描线)
InputThe input file consists of several test cases. Each test case starts with a line containing a single integer n (1<=n<=100) of available maps. The n following lines describe one map each. Each of these lines contains four numbers x1;y1;x2;y2 (0<=x1<x2<=100000;0<=y1<y2<=100000), not necessarily integers. The values (x1; y1) and (x2;y2) are the coordinates of the top-left resp. bottom-right corner of the mapped area.
The input file is terminated by a line containing a single 0. Don’t process it.OutputFor each test case, your program should output one section. The first line of each section must be “Test case #k”, where k is the number of the test case (starting with 1). The second one must be “Total explored area: a”, where a is the total explored area (i.e. the area of the union of all rectangles in this test case), printed exact to two digits to the right of the decimal point.
Output a blank line after each test case.
Sample Input
2
10 10 20 20
15 15 25 25.5
0
Sample Output
Test case #1
Total explored area: 180.00
题解:扫描线常规操作,如果不会先看大神的讲解再来:https://blog.csdn.net/xianpingping/article/details/83032798
#include<bits/stdc++.h>
using namespace std;
const int maxn=;
double x[maxn];
struct node
{
double l,r,h;
int d;
bool operator < (const node &a)const//按纵坐标从小到大排序
{
return h<a.h;
}
}line[maxn];
int cnt[maxn<<];//cnt[rt]表示该节点的覆盖次数,只要不为0就是被覆盖过
double sum[maxn<<];//线段树sum[rt]中每一个节点都是一个区间,sum[rt]表示该节点区间中的总有效覆盖长度
double area;
void pushup(int l,int r,int rt)
{
if(cnt[rt])//如果该节点(就是一个区间)全部被覆盖,那么sum就是这个区间的长度了~
sum[rt]=x[r+]-x[l];//x的下标是点,对于线段树的一个区间要进行右边下标+1再减去左边
else //否则要进行左右儿子的加和,因为不连续啊~
sum[rt]=sum[rt*]+sum[rt*+];
}
void update(int L,int R,int v,int l,int r,int rt)//在L,R区间覆盖次数加上v,即如果v为1就加1,为-1就减1
{
if(L<=l&&R>=r)
{
cnt[rt]+=v;
pushup(l,r,rt);//改变了cnt数组后要重新pushup
return ;
}
int mid=(l+r)/;//下面常规操作~
if(L<=mid)
update(L,R,v,l,mid,rt*);
if(R>=mid+)
update(L,R,v,mid+,r,rt*+);
pushup(l,r,rt);
}
int main()
{
int t,k=;
while(cin>>t&&t)
{
memset(cnt,,sizeof(cnt));//初始化全部为0
memset(sum,,sizeof(sum));
area=; //求得面积
int n=,m=;//x数组得最大元素个数,line数组得最大元素个数
for(int i=;i<=t;i++)//记录信息
{
double x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
x[++n]=x1;
x[++n]=x2;
line[++m]=(node){x1,x2,y1,};
line[++m]=(node){x1,x2,y2,-};
}
sort(x+,x++n);//对x数组从小打大排序
sort(line+,line++m);//对line扫描线数组按高度(即y)从小到大排序
int r=unique(x+,x++n)-x-;//r个不同的x将一条线段分成r-1个小区间,这也是后面查询总区长度是1到r-1和R--的原因
for(int i=;i<m;i++)//这里是对扫描线进行扫描~,扫描m-1次即可
{
int L=lower_bound(x+,x+r+,line[i].l)-x;
int R=lower_bound(x+,x+r+,line[i].r)-x;
R--;//每一个节点是一个区间,这里是将点转化为区间的操作
update(L,R,line[i].d,,r-,);
area+=sum[]*(line[i+].h-line[i].h);//用总有效长度乘上两条扫描线之间的距离即得到该块面积
}
printf("Test case #%d\nTotal explored area: %.2f\n\n",k++,area);
}
return ;
}
P - Atlantis (线段树+扫描线)的更多相关文章
- hdu1542 Atlantis 线段树--扫描线求面积并
There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some ...
- HDU 1542 - Atlantis - [线段树+扫描线]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542 Time Limit: 2000/1000 MS (Java/Others) Memory Li ...
- HDU 1542 Atlantis (线段树 + 扫描线 + 离散化)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- 【42.49%】【hdu 1542】Atlantis(线段树扫描线简析)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s) ...
- POJ 1151 - Atlantis 线段树+扫描线..
离散化: 将所有的x轴坐标存在一个数组里..排序.当进入一条线段时..通过二分的方式确定其左右点对应的离散值... 扫描线..可以看成一根平行于x轴的直线..至y=0开始往上扫..直到扫出最后一条平行 ...
- POJ1151 Atlantis 线段树扫描线
扫描线终于看懂了...咕咕了快三个月$qwq$ 对于所有的横线按纵坐标排序,矩阵靠下的线权值设为$1$,靠上的线权值设为$-1$,然后执行线段树区间加减,每次的贡献就是有效宽度乘上两次计算时的纵坐标之 ...
- POJ 1151:Atlantis 线段树+扫描线
Atlantis Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 19374 Accepted: 7358 Descrip ...
- hdu 1542 Atlantis (线段树扫描线)
大意: 求矩形面积并. 枚举$x$坐标, 线段树维护$[y_1,y_2]$内的边是否被覆盖, 线段树维护边时需要将每条边挂在左端点上. #include <iostream> #inclu ...
- hdu 1542&&poj 1151 Atlantis[线段树+扫描线求矩形面积的并]
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- hdu 1542 Atlantis(线段树,扫描线)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
随机推荐
- JSP编码问题解决方法
最近再看JSP相关知识,被中文乱码搞的很头大.找了好多方法终于找到了一个简单可行的方案. JSP中request和response操作默认编码为"ISO-8859-1",这是中文乱 ...
- Go语言之冒泡排序
package main //main函数 import "fmt" //相当于#include func main() { ar := [], , , , , , , , , } ...
- nginx重写常用写法
1.将http协议重写成https协议: (用户用http进行访问,但后端是https),则可添加80 http端口监听,然后进行https rewrite; server { listen ...
- 利用mysecureshell搭建sftp服务
1.下载对应的mysecureshell-1.33-1.x86_64.rpm包 2.安装mysecureshell-1.33-1.x86_64.rpm 3.添加ftp用户 useradd ftp 4. ...
- python期末考试复习
期末考试复习 补修的python跟着大一一起学,考试肯定不会出难,于是就敲了一些代码,把他们放到博客上,来记录一下 代码都是一段一段的,且python代码不是很多,所以我都写到了一个文件里,作为练习 ...
- nodejs(8) 使用ejs渲染动态页面
使用ejs渲染动态页面 步骤: 安装 ejs 模板引擎npm i ejs -S 使用 app.set() 配置默认的模板引擎 app.set('view engine', 'ejs') 使用 app. ...
- 最短路——迪杰斯特拉算法 HDU_3790
初识最短路,今天只弄了一个迪杰斯特拉算法,而且还没弄成熟,只会最基本的O(n^2),想弄个优先队列都发现尼玛被坑爆了,那个不应该用迪杰斯特拉算法写 表示还是不会优化版的迪杰斯特拉算法,(使用优先队列) ...
- i春秋-web-爆破-1
题目内容:flag就在某六位变量中. 题目 include "flag.php"; $a = @$_REQUEST['hello']; if(!preg_match('/^\w*$ ...
- 小程序转义字符去空格
<text ].specInfo}}</text> 在微信小程序开发过程中,有时候会用到常用的一些特殊字符如:‘<’.‘>’.‘&’.‘空格’等,微信小程序同样支 ...
- HDU - 1251 字典树模板题
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀). Input输入数据的第一部 ...