Atlantis(线段树扫描线求面积)

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 file 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.

Output a blank line after each test case. 这里看到我写了两次并且两次都用了粗体,就应该知道我wa在哪里了吧。坑哭了,没看到这细节。还有一个就是要注意这个是多组样例的,所以千万要记得tree数组要初始化。我和其他人的写法不太一样,因为按点写线段我实在理解不了,也不太会,更看不懂,所以我就直接按照线段写,即l+1 == r是叶子节点。这样的话感觉好写一点。剩下的就是离散化一下了,可以看成一个板子了。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 2e5+5;
double x[maxn];
int edge_num;
struct Edge
{
    double left, right, height;
    int flag;
    bool operator< (const Edge& obj) const
    {
        return ((height < obj.height) || (height == obj.height && flag > obj.flag));
    }
}edge[maxn];
struct node
{
    int sum;
    double len;
}tree[maxn<<2];

void AddEdge(double _left, double _right, double _height, int _flag)
{
    edge[++edge_num].left = _left;
    edge[edge_num].right = _right;
    edge[edge_num].height = _height;
    edge[edge_num].flag = _flag;
}

void PushUp(int left, int right, int cur)
{
    if(tree[cur].sum)
        tree[cur].len = x[right]-x[left];
    else
        tree[cur].len = tree[cur<<1].len+tree[cur<<1|1].len;
}

void update(int l, int r, int cur, int _from, int _to, int val)
{
    if(_from <= l && r <= _to)
    {
        tree[cur].sum += val;
        PushUp(l, r, cur);
        return ;
    }
    if(l+1 == r)    return ;
    int mid = (l+r)>>1;
    if(_from <= mid)    update(l, mid, cur<<1, _from, _to, val);
    if(_to >= mid)   update(mid, r, cur<<1|1, _from, _to, val);
    PushUp(l, r, cur);
}

int main()
{
    int n, cas = 1;
    while(~scanf("%d", &n), n)
    {
        memset(tree, 0, sizeof(tree));
        edge_num = 0;
        for(int i = 1; i <= n; i++)
        {
            double x1, x2, y1, y2;
            scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
            AddEdge(x1, x2, y1, 1);
            AddEdge(x1, x2, y2, -1);
            x[(i<<1)-1] = x1;   x[(i<<1)] = x2;
        }
        printf("Test case #%d\n", cas++);
        sort(x+1, x+1+(n<<1));
        sort(edge+1, edge+1+edge_num);
        int num = unique(x+1, x+1+(n<<1))-x-1;
        double result = 0.0;
        for(int i = 1; i < edge_num; i++)
        {
            int l = lower_bound(x+1, x+1+num, edge[i].left)-x;
            int r = lower_bound(x+1, x+1+num, edge[i].right)-x;
            update(1, num, 1, l, r, edge[i].flag);
            while(edge[i].height == edge[i+1].height)
            {
                i++;
                l = lower_bound(x+1, x+1+num, edge[i].left)-x;
                r = lower_bound(x+1, x+1+num, edge[i].right)-x;
                update(1, num, 1, l, r, edge[i].flag);
            }
            result += tree[1].len*(edge[i+1].height-edge[i].height);
        }
        printf("Total explored area: %.2lf\n\n", result);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_40788897/article/details/99677780