Atlantis POJ - 1151 (扫描线求矩形面积并)

题目链接:http://poj.org/problem?id=1151

题目给了n个矩形,每个矩形给了左下角右上角的坐标,矩形可能会重叠,求的是矩形最后的面积。因为变化范围比较大,我们要用到离散化,重点说一说扫描线的过程: 
下面有几个矩形 

现在我们假设有一根扫描线,从下往上开始扫描 

如图所示,我们可以把整个矩形分成如图各个颜色不同的小矩形,那么这个小矩形的高就是我们扫过的距离,那么剩下了一个变量,那就是矩形的长一直在变化。
我们的线段树就是维护矩形的长,我们给每一个矩形的上下边进行标记,下面的边标记为1,上面的边标记为-1,每遇到一个矩形时,我们知道了标记为1的边,我们就加进来这一条矩形的长,等到扫描到-1时,证明这一条边需要删除。
还要注意这里的线段树指的并不是线段的一个端点,而指的是一个区间,所以我们要计算的时候r+1和r-1
再提一下离散化,离散化就是把一段很大的区间映射到一个小区间内,这样会节省大量空间,要进行离散化,我们先对端点进行排序,然后去重,然后二分找值就可以了 

 

 

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define ll long long

using namespace std;

const int maxn = 222 + 10;
struct node
{
    double x, y, h;
    int flag;
} pos[maxn];

int cnt[maxn << 3];
double sum[maxn << 3],X[maxn];

bool cmp(node a, node b){
	return a.h < b.h;
}

void pushup(int cur,int l,int r)
{
   if(cnt[cur])  sum[cur] = X[r + 1] - X[l]; 
   else sum[cur] = sum[cur<<1] + sum[cur<< 1 | 1];
}

void update(int l, int r, int val, int cur, int cl,int cr)
{
    if(l <= cl && cr <= r)
    {
       cnt[cur] += val;
       pushup(cur, cl, cr);
       return ;
    }

    int mid = cl + cr >> 1;
    if(l <= mid)update(l, r, val, cur << 1, cl, mid);
    if(r > mid)update(l, r, val, cur << 1 | 1, mid + 1, cr);
    pushup(cur, cl, cr);
}

int main()
{
    int n;
    int t=1;
    while(scanf("%d", &n) && n)
    {
        memset(cnt, 0, sizeof(cnt));
        memset(sum, 0, sizeof(sum));
        int xx = 0, hh = 0;
        for(int i = 1; i <= n; i++)
        {
            double x1, y1, x2, y2;
            scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2);
            X[++xx] = x1;
            X[++xx] = x2;
            pos[++hh] = node{x1, x2, y1, 1};
            pos[++hh] = node{x1, x2, y2,-1};
        }

        sort(X + 1, X + 1 + xx);
        sort(pos + 1, pos + 1 + hh, cmp);
        xx=unique(X + 1, X + xx + 1) - X - 1;
        double ans = 0.0;
        for(int i = 1; i <= hh; i++)
        {

            int l=lower_bound(X + 1, X + xx + 1, pos[i].x) - X;
            int r=lower_bound(X + 1, X + xx + 1, pos[i].y) - X;
            r--;
            update(l, r, pos[i].flag, 1, 1, xx - 1);
            ans += sum[1] * (pos[i + 1].h - pos[i].h);
        }
        printf("Test case #%d\nTotal explored area: %.2f\n\n", t++, ans);
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值