Atlantis --- 线段树 + 扫描线

传送门poj1151
poj最近又炸了


这里写图片描述

(翻译什么的就算了,看看数据范围和样例就差不多了)


分析

标准的面积并,离散化一波直接求,注意是实数

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>

#define IL inline

using namespace std;

struct node
{
    node *lch, *rch;
    double len;
    int cnt;
    IL node()
    {
        lch = rch = 0;
        len = 0;
        cnt = 0;
    }
} *root;

struct segment
{
    double x, y1, y2;
    int k;
    IL segment(double x_ = 0, double y1_ = 0, double y2_ = 0, int k_ = 0)
    {
        x = x_; y1 = y1_; y2 = y2_; k = k_;
    }
    friend bool operator < (const segment &a, const segment &b)
    {
        return a.x < b.x;
    }
}seg[205];

double num[205];
queue<node *>Q;

IL void del(node *p)
{
    if(!p) return ;
    del(p->lch); del(p->rch);
    Q.push(p);
}

IL node* newnode()
{
    if(Q.empty()) return new node;
    node *p = Q.front(); Q.pop();
    p->lch = p->rch = 0;
    p->len = 0; p->cnt = 0;
    return p;
}

IL void pushup(node *p, int l, int r)
{
    if(p->cnt > 0)
        p->len = num[r + 1] - num[l]; 
    else
        p->len = (l == r ? 0 : p->lch->len + p->rch->len);
}

IL void build(node *p, int l, int r)
{
    if(l == r) return ;
    int mid = (l + r) >> 1;
    p->lch = newnode(); build(p->lch, l, mid);
    p->rch = newnode(); build(p->rch, mid + 1, r);
}

IL void update(node *p, int l, int r, int x, int y, int k)
{
    if(l == x && r == y)
    {
        p->cnt += k;
        pushup(p, l, r);
        return ;
    }
    int mid = (l + r) >> 1;
    if(y <= mid) update(p->lch, l, mid, x, y, k); else
    if(mid < x) update(p->rch, mid + 1, r, x, y, k); else
    {
        update(p->lch, l, mid, x, mid, k);
        update(p->rch, mid + 1, r, mid + 1, y, k);
    }
    pushup(p, l, r);
}

int main()
{
    for(int n, m, T = 1; scanf("%d", &n); ++T)
    {
        if(!n) break;
        m = 0;
        del(root);

        for(int i = 1, k = 0; i <= n; ++i)
        {
            double x1, x2, y1, y2;
            scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2);
            seg[++k] = segment(x1, y1, y2, 1); seg[++k] = segment(x2, y1, y2, -1);
            num[++m] = y1; num[++m] = y2;
        }
        n <<= 1;
        sort(seg + 1, seg + n + 1);
        sort(num + 1, num + m + 1);
        m = unique(num + 1, num + m + 1) - (num + 1);

        root = newnode();
        build(root, 1, m - 1);

        double ans = 0;
        for(int i = 1, y1, y2; i <= n; ++i)
        {
            ans += (seg[i].x - seg[i - 1].x) * root->len;
            y1 = lower_bound(num + 1, num + m + 1, seg[i].y1) - num;
            y2 = lower_bound(num + 1, num + m + 1, seg[i].y2) - num - 1;
            update(root, 1, m - 1, y1, y2, seg[i].k);
        }
        printf("Test case #%d\nTotal explored area: %.2lf\n\n", T, ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_27121257/article/details/81201249