Atlantis
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 21734   Accepted: 8179

Description

There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the island. But unfortunately, these maps describe different regions of Atlantis. Your friend Bill has to know the total area for which maps exist. You (unwisely) volunteered to write a program that calculates this quantity.

Input

The input 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.

Output

For 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

Source


[10-13-2016]
有一条线从下往上扫,维护当前的x轴覆盖总长度
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int N=;
#define m (l+r)/2
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
#define lc o<<1
#define rc o<<1|1
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n,cnt=;
double x1,y1,x2,y2,mp[N];
struct seg{
double l,r,h;
int f;//1 or -1
seg(double a=,double b=,double c=,int d=):l(a),r(b),h(c),f(d){}
bool operator <(const seg &r)const{return h<r.h;}
}a[N];
struct node{
double sum;
int cov;
}t[N<<];
inline int Bin(double v){
int l=,r=cnt;
while(l<=r){
int mid=(l+r)>>;
if(mp[mid]==v) return mid;
else if(v<mp[mid]) r=mid-;
else l=mid+;
}
return -;
}
inline void pushUp(int o,int l,int r){
if(t[o].cov) t[o].sum=mp[r+]-mp[l];
else if(l==r) t[o].sum=;
else t[o].sum=t[lc].sum+t[rc].sum;
}
void update(int o,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr){
t[o].cov+=v;
pushUp(o,l,r);
}else{
if(ql<=m) update(lson,ql,qr,v);
if(m<qr) update(rson,ql,qr,v);
pushUp(o,l,r);
}
}
int cas=;
int main(int argc, const char * argv[]) {
while((n=read())){
double ans=;
for(int i=;i<=n;i++){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
a[i*-]=seg(x1,x2,y1,);
a[i*]=seg(x1,x2,y2,-);
mp[*i-]=x1;
mp[*i]=x2;
}
sort(mp+,mp++*n);
sort(a+,a++*n);
cnt=;mp[++cnt]=mp[];
for(int i=;i<=*n;i++)
if(mp[i]!=mp[i-]) mp[++cnt]=mp[i];
memset(t,,sizeof(t));
for(int i=;i<=*n-;i++){//最后一个不用
int ql=Bin(a[i].l),qr=Bin(a[i].r)-;
if(ql<=qr) update(,,cnt,ql,qr,a[i].f);
ans+=t[].sum*(a[i+].h-a[i].h);
}
printf("Test case #%d\n",++cas);
printf("Total explored area: %.2f\n\n",ans);
} return ;
}

线段树需要插入线段,删除线段,求线段覆盖的总长度,貌似还是用标记永久化比较方便,否则删(我)除(没)很(写)麻(出)烦(来)

注意这个线段树节点是一段区间哦

离散化m忘清0了 WA了几次

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int N=;
#define lson x<<1,l,mid
#define rson x<<1|1,mid+1,r
#define lc x<<1
#define rc x<<1|1
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n;
double x1,y1,x2,y2;
struct Seg{
double l,r,y;
int f;
Seg(double l=,double r=,double y=,int f=):l(l),r(r),y(y),f(f){}
bool operator <(const Seg &a)const{return y<a.y;}
}a[N];
double mp[N];int m;
void iniMP(){
sort(mp+,mp++m);
int p=;
mp[++p]=mp[];
for(int i=;i<=m;i++) if(mp[i]!=mp[i-]) mp[++p]=mp[i];
m=p;
}
inline int Bin(double v){
int l=,r=m;
while(l<=r){
int mid=(l+r)>>;
if(v==mp[mid]) return mid;
else if(v<mp[mid]) r=mid-;
else l=mid+;
}
return ;
}
struct node{
double sum;
int cov;
node():sum(),cov(){}
}t[N<<];
void pushUp(int x,int l,int r){
if(t[x].cov) t[x].sum=mp[r+]-mp[l];
else if(l==r) t[x].sum=;
else t[x].sum=t[lc].sum+t[rc].sum;
}
void segCov(int x,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr) t[x].cov+=v,pushUp(x,l,r);
else{
int mid=(l+r)>>;
if(ql<=mid) segCov(lson,ql,qr,v);
if(mid<qr) segCov(rson,ql,qr,v);
pushUp(x,l,r);
}
} int cas=;
int main(int argc, const char * argv[]) {
while((n=read())){
m=;
for(int i=;i<=n;i++){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
a[i*-]=Seg(x1,x2,y1,);
a[i*]=Seg(x1,x2,y2,-);
mp[++m]=x1;mp[++m]=x2;
}
iniMP();
n<<=;
sort(a+,a++n);
memset(t,,sizeof(t));
double ans=;
for(int i=;i<=n-;i++){
int ql=Bin(a[i].l),qr=Bin(a[i].r)-;
if(ql<=qr) segCov(,,m,ql,qr,a[i].f);
ans+=t[].sum*(a[i+].y-a[i].y);
}
printf("Test case #%d\n",++cas);
printf("Total explored area: %.2f\n\n",ans);
} return ;
}
 

POJ1151Atlantis 矩形面积并[线段树 离散化 扫描线]的更多相关文章

  1. POJ 1151Atlantis 矩形面积并[线段树 离散化 扫描线]

    Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 21734   Accepted: 8179 Descrip ...

  2. hdu1542 矩形面积并(线段树+离散化+扫描线)

    题意: 给你n个矩形,输入每个矩形的左上角坐标和右下角坐标. 然后求矩形的总面积.(矩形可能相交). 题解: 前言: 先说说做这道题的感受: 刚看到这道题顿时就懵逼了,几何 烂的渣渣.后来从网上搜题解 ...

  3. poj-1151矩形面积并-线段树

    title: poj-1151矩形面积并-线段树 date: 2018-10-30 22:35:11 tags: acm 刷题 categoties: ACM-线段树 概述 线段树问题里的另一个问题, ...

  4. 【POJ 2482】 Stars in Your Window(线段树+离散化+扫描线)

    [POJ 2482] Stars in Your Window(线段树+离散化+扫描线) Time Limit: 1000MS   Memory Limit: 65536K Total Submiss ...

  5. HDU1542 Atlantis —— 求矩形面积并 线段树 + 扫描线 + 离散化

    题目链接:https://vjudge.net/problem/HDU-1542 There are several ancient Greek texts that contain descript ...

  6. Codeforces 610D Vika and Segments 线段树+离散化+扫描线

    可以转变成上一题(hdu1542)的形式,把每条线段变成宽为1的矩形,求矩形面积并 要注意的就是转化为右下角的点需要x+1,y-1,画一条线就能看出来了 #include<bits/stdc++ ...

  7. POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算

    求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的, ...

  8. hdu1542线段树+离散化+扫描线

    参考博客: http://blog.csdn.net/xingyeyongheng/article/details/8927732 总的来说就是用一条(假想的)线段去平行x轴从下往上扫描,扫描的过程中 ...

  9. Picture POJ - 1177 线段树+离散化+扫描线 求交叉图像周长

    参考  https://www.cnblogs.com/null00/archive/2012/04/22/2464876.html #include <stdio.h> #include ...

随机推荐

  1. webserver[实时查询当天的天气情况]

    1.webserver是什么? 日常生活中经常会使用到webserver,注册时,会收到验证码,购买东西时,会收到短信,假如,A公司网站和B公司合作,那么A公司注册对的用户可以直接推送给B网站,那怎么 ...

  2. Unity3D 5.x 简单实例 - 脚本编写

    1,Vector3 类型变量存储向量坐标值 Vector3.forward Vector3(0,0,1) Vector3.up Vector3(0,1,0) Vector3.right Vector3 ...

  3. java入门笔记(1)

    上图表达的是我们写的java程序是怎么在电脑上运行并算出结果的.编译器判断语法是否正确,如果错误,不能生成.class文件. JVM(Java Virtual Machine)是java虚拟机. JV ...

  4. css3制作旋转立方体相册

    首先让我们来看一下最终效果图: 当鼠标放在图片上是介个样子滴: 是不是觉得很好看?那接下来就一起制作吧! 我个人觉得编程,首先是思路,然后是代码,一起分析一下这个效果的思路. 1.背景颜色,它属于一种 ...

  5. sharepoint

    <script> $("#sideNavBox").css('display','none'); $("#contentBox").css('mar ...

  6. iOS Class 使用NSProxy和NSObject设计代理类的差异

    经常发现在一些需要使用消息转发而创建代理类时, 不同的程序员都有着不同的使用方法, 有些采用继承于NSObject, 而有一些采用继承自NSProxy. 二者都是Foundation框架中的基类, 并 ...

  7. 多人开发Xcode工程冲突,打不开解决办法

    在公司多人协作开发,相信好多程序员都遇到非常忧伤的问题,就是工程打不开,这样就无从下手,好多程序怨只能再从代码服务器上下载一份新的代码,今天军哥教你几个小技巧,让你的bigger瞬间提升一个档次 在公 ...

  8. Android 应用程序集成Google 登录及二次封装

    谷歌登录API:  https://developers.google.com/identity/sign-in/android/ 1.注册并且登录google网站 https://accounts. ...

  9. 基于redis分布式缓存实现(新浪微博案例)

    第一:Redis 是什么? Redis是基于内存.可持久化的日志型.Key-Value数据库 高性能存储系统,并提供多种语言的API. 第二:出现背景 数据结构(Data Structure)需求越来 ...

  10. ajax参数设置略解

    通过ajax可以直接由页面访问到服务器.做到不刷新页面,就能刷新数据,为开发带来很大的便利. 1.ajax方式的参数及其功能: $.ajax({ type : "POST", // ...