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

有点难,扫描线易懂,离散化然后线段树处理有点不太好理解。

因为这里是一个区间,所有在线段树中更新时,必须是一个长度大于1的区间才是有效的,比如[l,l]这是一根线段,而不是区间了。

AC代码

#include <stdio.h>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 200 + 5;

struct Line{
    double x, y1, y2;
    int flag;
    Line(double a, double b, double c, int d) {
        x = a; y1 = b; y2 = c; flag = d;
    }
    bool operator < (const Line& a) const {
        return x < a.x;
    }
};

vector<Line> line;
map<double, int> Hash;
vector<double> y;

double p[maxn << 2];    // 区间长度
int covers[maxn << 2];  // 覆盖次数
double len[maxn << 2];  // 覆盖长度

void buildTree(int o, int l, int r) {
    len[o] = covers[o] = 0;
    p[o] = y[r] - y[l];
    if(l + 1 != r) {
        int m = (l+r) / 2;
        buildTree(o*2, l, m);
        buildTree(o*2+1, m, r);
    }
}

int ul, ur; 
void update(int o, int l, int r, int f) {
    if(l+1 == r) {
        covers[o] += f;
        if(covers[o] == 0) len[o] = 0;
        else len[o] = p[o]; 
    } 
    else {
        int m = (l+r) / 2;
        if(ul < m) update(o*2, l, m, f);
        if(m < ur) update(o*2+1, m, r, f);
        // pushUp
        len[o] = len[o*2] + len[o*2+1];
    }
}

int main() {
    int n, kase = 1;
    while(scanf("%d", &n) == 1 && n) {
        Hash.clear(); line.clear(); y.clear();
        double x1, y1, x2, y2;
        for(int i = 0; i < n; i++) {
            scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
            line.push_back(Line(x1, y1, y2, 1));
            line.push_back(Line(x2, y1, y2, -1));
            y.push_back(y1);
            y.push_back(y2);
        }
        
        sort(line.begin(), line.end());
        sort(y.begin(), y.end());
        y.erase(unique(y.begin(), y.end()), y.end());
        for(int i = 0; i < (int)y.size(); i++) {
            Hash[y[i]] = i;
        }
        
        buildTree(1, 0, y.size()-1);
        double ans = 0;
        for(int i = 0; i < line.size(); i++) {
            if(i > 0) ans += (line[i].x - line[i-1].x) * len[1];
            ul = Hash[line[i].y1]; ur = Hash[line[i].y2];
            update(1, 0, y.size()-1, line[i].flag);
        }
        printf("Test case #%d\nTotal explored area: %.2f\n\n", kase++, ans);
    }
    return 0;
}

如有不当之处欢迎指出!

posted @ 2018-04-17 17:34  flyawayl  阅读(534)  评论(0编辑  收藏  举报