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

贴几个大佬的博客帮助理解

https://blog.csdn.net/xingyeyongheng/article/details/8927732
http://www.aizhuanji.com/a/AWbkpGxj.html
https://www.cnblogs.com/liwenchi/p/7259171.html
https://blog.csdn.net/qq_18661257/article/details/47658191
http://www.cnblogs.com/fenshen371/p/3214092.html

因为线段树节点存的是区间的长度,那么就导致叶子节点单独的一个数就没有意义了,所以这里采用了[)左闭右开的这种写法,这样就有意义了

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <set>
#include <cctype>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define MOD 1e9+7
#define PI acos(-1)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 222;
int n;
struct node {
    double l, r, h; //标记线段位置及高度
    int flag;//标记上下边

    node() {} //不懂为什么这么写,但是没有这一句就不能像下面一样使用初始化列表
    node(double a, double b, double c, int d): l(a), r(b), h(c), flag(d) {}
    bool operator <(const node &a)const {//重载< 用于下面的排序
        return h < a.h;
    }
} ss[maxn << 2];

double sum[maxn << 2]; //记录面积
int cover[maxn << 2]; //记录是否被覆盖
double Hash[maxn];//离散化数组,一开始开成了int却是MLE,好奇怪
int my_search(double key, int k) {//因为不能使用lower_bound(),所以只好自己手写二分查找
    int l = 0;
    int r = k - 1;//因为Hash是从0开始存的,所以范围是[0,k-1]
    while(l <= r) {
        int mid = (l + r) >> 1;
        if(Hash[mid] == key) return mid;
        else if(Hash[mid] > key) r = mid - 1;
        else l = mid + 1;
    }
    return -1;
}
void push_up(int rt, int l, int r) {
    if(cover[rt])  sum[rt] = Hash[r + 1] - Hash[l];
    /*如果这个节点已经被完全覆盖,那么长度就是右边减左边z
    注意这里要+1
    */
    else if(l == r)  sum[rt] = 0;//当前是一个点,不是很懂
    else sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];//如果当前这个区间没有被完全覆盖,区间长度就是他的子区间的和
}
void  updata(int L, int R, int flag, int l, int r, int rt) {
    if(L <= l && r <= R) {
        cover[rt] += flag;//更新cover
        push_up(rt, l, r);
        return;
    }
    int m = (l + r) >> 1;
    if(L <= m) updata(L, R, flag, lson);
    if(R > m) updata(L, R, flag, rson);
    push_up(rt, l, r);
    return ;
}
int main() {
    int cas = 0;
    while(~scanf("%d", &n), n) {
        memset(sum, 0, sizeof(sum));
        memset(cover, 0, sizeof(cover));
        cas++;
        int cnt = 0;
        for(int i = 1; i <= n; i++) {
            double x1, x2, y1, y2;
            scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
            ss[cnt] = {x1, x2, y1, 1};
            Hash[cnt++] = x1;
            ss[cnt] = {x1, x2, y2, -1};
            Hash[cnt++] = x2;
        }
        sort(ss, ss + cnt);
        sort(Hash, Hash + cnt);
        int k = unique(Hash, Hash + cnt) - Hash;//去重
        double ans = 0;
        for(int i = 0; i < cnt - 1; i++) {
            int l = my_search(ss[i].l, k);
            int r = my_search(ss[i].r, k) - 1;
            updata(l, r, ss[i].flag, 0, k - 1, 1);
            ans += sum[1] * (ss[i + 1].h - ss[i].h);
        }
        printf("Test case #%d\nTotal explored area: %.2f\n\n", cas, ans);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/81190351
今日推荐