poj3277--City Horizon(线段树+离散化+扫描线)

City Horizon

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 16206   Accepted: 4414

Description

Farmer John has taken his cows on a trip to the city! As the sun sets, the cows gaze at the city horizon and observe the beautiful silhouettes formed by the rectangular buildings.

The entire horizon is represented by a number line with N (1 ≤ N ≤ 40,000) buildings. Building
i‘s silhouette has a base that spans locations Ai through
Bi along the horizon (1 ≤ Ai < Bi ≤ 1,000,000,000) and has height
Hi (1 ≤ Hi ≤ 1,000,000,000). Determine the area, in square units, of the aggregate silhouette formed by all
N buildings.

Input

Line 1: A single integer: N

Lines 2..N+1: Input line i+1 describes building i with three space-separated integers:
Ai, Bi, and Hi

Output

Line 1: The total area, in square units, of the silhouettes formed by all
N buildings

Sample Input

4
2 5 1
9 10 4
6 8 2
4 6 3

Sample Output

16

Hint

The first building overlaps with the fourth building for an area of 1 square unit, so the total area is just 3*1 + 1*4 + 2*2 + 2*3 - 1 = 16.

和poj1151相同,求解矩形的并的面积http://blog.csdn.net/winddreams/article/details/38495093

按x轴有左向右扫描,对y值进行离散化,为了将每个段连接起来,所以左右子树应该是[l,mid],[mid,r],每段的差是1,不是0,这样可以防止,忽略掉mid+1到mid这一段,然后判断,只有lazy大于0时,这一个节点的所有长度都加进去,不然节点大小 = 左右子树的和

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define maxn 81000
#define LL __int64
struct node1
{
    LL x, y1 , y2 ;
    LL flag ;
} p[maxn<<2];
struct node2
{
    LL l , r ;
    LL sum ;
} cl[maxn<<2];
LL lazy[maxn<<2];
LL s[maxn<<2] ;
bool cmp(node1 a,node1 b)
{
    return a.x < b.x ;
}
void push_up(int rt)
{
    if( lazy[rt] )
        cl[rt].sum = cl[rt].r - cl[rt].l ;
    else
        cl[rt].sum = cl[rt<<1].sum + cl[rt<<1|1].sum ;
}
void creat(int rt,int l,int r)
{
    cl[rt].l = s[l] ;
    cl[rt].r = s[r] ;
    if( r - l > 1 )
    {
        creat(rt<<1,l,(l+r)/2);
        creat(rt<<1|1,(l+r)/2,r);
    }
    else
        cl[rt].sum = 0 ;
    return ;
}
void update(int rt,LL l,LL r,int flag)
{
    if( l == cl[rt].l && r == cl[rt].r )
    {
        lazy[rt] += flag ;
        push_up(rt);
        return ;
    }
    else
    {
        if( cl[rt<<1].r > l )
        {
            LL k = cl[rt<<1].r < r ? cl[rt<<1].r : r ;
            update(rt<<1,l,k,flag);
        }
        if( cl[rt<<1|1].l < r )
        {
            LL k = cl[rt<<1|1].l > l ? cl[rt<<1|1].l : l ;
            update(rt<<1|1,k,r,flag);
        }
        push_up(rt);
    }
}
int main()
{
    LL i , n , x1 , x2 , h , low , ans ;
    while(scanf("%I64d", &n)!=EOF)
    {
        for(i = 0 ; i < n ; i++)
        {
            scanf("%I64d %I64d %I64d", &x1, &x2, &h);
            p[i].x = x1 ;
            p[i].y1 = 0 ;
            p[i].y2 = h ;
            p[i].flag = 1 ;
            p[i+n].x = x2 ;
            p[i+n].y1 = 0 ;
            p[i+n].y2 = h ;
            p[i+n].flag = -1 ;
            s[i+1] = h ;
        }
        s[n+1] = 0 ;
        sort(s+1,s+(n+2));
        sort(p,p+2*n,cmp);
        creat(1,1,n+1);
        update(1,p[0].y1,p[0].y2,p[0].flag);
        ans = 0 ;
        for(i = 1 ; i < 2*n ; i++)
        {
            ans += ( p[i].x - p[i-1].x )*cl[1].sum;
            update(1,p[i].y1,p[i].y2,p[i].flag);
        }
        printf("%I64d\n", ans);
    }
    return 0;
}

poj3277--City Horizon(线段树+离散化+扫描线),布布扣,bubuko.com

时间: 2024-10-10 23:02:33

poj3277--City Horizon(线段树+离散化+扫描线)的相关文章

POJ 3277 City Horizon(线段树+扫描线+离散化)

题目地址:POJ 3277 水题..稍微处理一下然后用求面积并的方法求即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <

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

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

hdu1828 Picture(线段树+离散化+扫描线)两种方法

C - Picture Time Limit:2000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Description A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical or

POJ 2482 Stars in Your Window 线段树+离散化+扫描线

题面据说很美- 每个星星可以根据在窗口的左下角和右上角两个位置建立两条扫描线,之后就是简单的区间增减和求最大值操作了. 注意要处理在边界上的星星是不算的情况,其实只要把左右边界分别增减一个eps即可. #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set> #include <vector> #include <

HDU 1542 Atlantis 线段树+离散化+扫描线

题意:给出一些矩形的最上角坐标和右下角坐标,求这些矩形的面积并. NotOnlySuccess 线段树专辑中扫描线模板题,弱智的我对着大大的代码看了一下午才搞懂. 具体见思路见注释=.= #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #define lson rt<<1,l,mid #define rson rt<<1|1,mid

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

[POJ 2482] Stars in Your Window(线段树+离散化+扫描线) Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11294   Accepted: 3091 Description Fleeting time does not blur my memory of you. Can it really be 4 years since I first saw you? I still remembe

HDU 3642 线段树+离散化+扫描线

题意:给你N个长方体的左下角和右上角坐标,问你空间中有多少体积是被大于两个不同的立方体覆盖的.x,y~10^6 z~500 考虑到给的z比较小,所以可以直接枚举z,然后跑二维的扫描线就好. 关于处理被不同的线段覆盖三次的问题,可以维护四个信息,cnt,once,twice,more,然后相互推出结果就好. #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #

hdu1255--覆盖的面积(线段树+离散化+扫描线)

E - 覆盖的面积 Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input 输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含

poj1151-- Atlantis(线段树+离散化+扫描线)

Atlantis Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of pa