POJ 1151 Atlantis 扫描线+线段树

点击打开链接

Atlantis

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 17252   Accepted: 6567

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

Mid-Central European Regional Contest 2000

求矩阵的并。

从第一条开始的竖边到最后一条竖边,逐条插入到线段树,并记录此时整个区间中被覆盖的实际长度,然后利用下一条竖边与当前竖边的x值差乘以现有的y轴覆盖实际长度就是此段覆盖的面积了。

//208K	16MS
#include<stdio.h>
#include<algorithm>
#define M 207
using namespace std;
double y[M];
struct Tree
{
    int l,r,mid,cover;
    double len;
}tree[M<<4];
struct Line
{
    double x,y1,y2;
    int dir;
}l[M<<4];
int cmp(Line a,Line b)
{
    return a.x<b.x;
}
void cal(int i)
{
    if(tree[i].cover>0)tree[i].len=y[tree[i].r]-y[tree[i].l];//如果被覆盖那么就是整段长度
    else if(tree[i].l+1==tree[i].r)tree[i].len=0;//未被覆盖且为叶子节点,则为0
    else tree[i].len=tree[i*2].len+tree[i*2+1].len;//非叶子节点即为下面子区间的覆盖总和
}
void build(int left,int right,int i)
{
    tree[i].l=left;tree[i].r=right;tree[i].mid=(left+right)>>1;
    tree[i].cover=0;tree[i].len=0;
    if(left+1!=right)
    {
        build(left,tree[i].mid,i*2);
        build(tree[i].mid,right,i*2+1);
    }
}
void insert(Line a,int i)
{
    Line t;
    if(y[tree[i].l]==a.y1&&y[tree[i].r]==a.y2)tree[i].cover+=a.dir;
    else
    {
        if(y[tree[i*2].r]>=a.y2)insert(a,i*2);
        else if(y[tree[i*2+1].l]<=a.y1)insert(a,i*2+1);
        else
        {
            t=a;
            t.y2=y[tree[i*2].r];
            insert(t,i*2);
            t=a;
            t.y1=y[tree[i*2+1].l];
            insert(t,i*2+1);
        }
    }
    cal(i);
}
int main()
{
    int n,cas=1;
    while(scanf("%d",&n),n)
    {
        double x1,y1,x2,y2,ans=0;
        int k=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            l[k].x=x1;l[k].y1=y1;l[k].y2=y2;l[k].dir=1;
            y[k++]=y1;
            l[k].x=x2;l[k].y1=y1;l[k].y2=y2;l[k].dir=-1;
            y[k++]=y2;
        }
        sort(l,l+k,cmp);
        sort(y,y+k);
        build(0,k-1,1);
        insert(l[0],1);
        for(int i=1;i<k;i++)
        {
            ans+=tree[1].len*(l[i].x-l[i-1].x);
            insert(l[i],1);
        }
        printf("Test case #%d\n",cas++);
        printf("Total explored area: %.2lf\n\n",ans);
    }
    return 0;
}

POJ 1151 Atlantis 扫描线+线段树,布布扣,bubuko.com

时间: 2024-10-17 00:24:46

POJ 1151 Atlantis 扫描线+线段树的相关文章

POJ 1151 Atlantis(线段树 + 扫描线)

转载请注明原文:http://www.cnblogs.com/burning-flame/p/5934653.html 题目链接:http://poj.org/problem?id=1151 题意: 给你 n 个矩形的对角线坐标,求 n 个矩形并集的面积. 做法: 扫描线 + 线段树. 因为作线段树的题遇到了扫描线,只是粗浅的了解了一下. 就像字面上的:线性扫描一遍,对于每个单元,因为某些事件的发生会有一些变化. 举个例子: 现有长度为 n 的数组a,同时有 n 个区间覆盖[li, ri],对于

POJ训练计划1177_Picture(扫描线/线段树+离散)

解题报告 题意: 求矩形周长和. 思路: 左扫上扫,扫过了. #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; struct Seg { int lx,rx,ly,ry,h,v; friend bool operator < (Seg a,Seg b) { re

POJ 1151 Atlantis(扫描线)

题目原链接:http://poj.org/problem?id=1151 题目中文翻译: POJ 1151 Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 25769   Accepted: 9477 Description 有几个古希腊文本包含传说中的亚特兰蒂斯岛的描述. 其中一些文本甚至包括岛屿部分地图. 但不幸的是,这些地图描述了亚特兰蒂斯的不同区域. 您的朋友Bill必须知道地图的总面积. 你(不

poj1151 Atlantis——扫描线+线段树

题目:http://poj.org/problem?id=1151 经典的扫描线问题: 可以用线段树的每个点代表横向被矩形上下边分割开的每一格,这样将一个矩形的出现或消失化为线段树上的单点修改: 每个格子记录两个值:c(矩形存在情况),sum(对当前答案作出贡献的长度): 将y离散化作为建树的依据: 一开始没想到线段树上的点应该是横向的格子,写了个乱七八糟: #include<iostream> #include<cstdio> #include<cstring> #i

Picture POJ - 1177(扫描线 + 线段树)

题意:求矩形并的面积.. 解析: 扫描线第一道题....自下而上扫描的... 如果不懂什么是扫描线戳我 #include <iostream> #include <cstdio> #include <sstream> #include <cstring> #include <map> #include <set> #include <vector> #include <stack> #include <q

【POJ】1151 Atlantis(线段树)

http://poj.org/problem?id=1151 经典矩形面积并吧.....很简单我就不说了... 有个很神的地方,我脑残没想到: 将线段变成点啊QAQ这样方便计算了啊 还有个很坑的地方,为毛每一次我精确地计算过空间可就是wa....一改大就ac...我无力了.. #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostrea

poj 1151 Atlantis (离散化 + 扫描线 + 线段树)

题目链接题意:给定n个矩形,求面积并,分别给矩形左上角的坐标和右上角的坐标. 分析: 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <cstring> 5 #include <cstdlib> 6 #include <algorithm> 7 #define LL __int64 8 #define lson l, mid, 2*rt

POJ&#183;1151 Atlantis&#183;线段树求矩形面积并

题目在这:http://poj.org/problem?id=1151 Atlantis Time Limit: 1000MS   Memory Limit: 10000K 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 is

poj 3277 City Horizon (线段树 扫描线 矩形面积并)

题目链接 题意: 给一些矩形,给出长和高,其中长是用区间的形式给出的,有些区间有重叠,最后求所有矩形的面积. 分析: 给的区间的范围很大,所以需要离散化,还需要把y坐标去重,不过我试了一下不去重 也不会出错, 所有的区间都能列出来,只是在查找的时候费点事. 给的矩形相当于在同一水平线上的,也就是y1坐标相当于为0,其他的就和 poj 1151 Atlantis 差不多了. 我写的思路是按照矩形面积并的思路写的: 但是还有另一种方法也是挺简单的,就是把给的矩形按照高从小到大排序,然后依次插入线段树