hdu 1542 矩形交(线段树)

来源:互联网 发布:网易电台录制软件 编辑:程序博客网 时间:2024/06/05 19:09

所谓的离散化,大家可以简单的理解为,将一组很大的数据,浓缩为一组很小的数据,用这组数据来代替原数据的作用,
比如给你1000个数,数的范围为(1,1e18)我们这里就可以用离散化,由于只有1000个数,我们可以用一个数组的下标代表提供的每一数,如果需要这个数据了,由于是下标,可以直接通过下标获得,如此就是离散化。
扫描线的知识提供一个大牛的博客:http://www.cnblogs.com/scau20110726/archive/2013/04/12/3016765.html
讲得很基础,是个很不错的博客
然后提醒一下这个扫描线要注意的问题就是区间的问题
一般的线段树以及我们的区间修改合并,都有一个共同点,就是不会出现区间缺失的现象,什么叫区间缺失,顾名思义,区间缺失就是缺少一些区间没有进行运算,这里的扫描线就会遇到这个问题。
普遍的,我们的线段树以及数据区间分布是这样的:
[1, a][a + 1, b][b + 1, c][c + 1, d][d + 1, e]…….
但是如果只是简简单单的用这个来解决扫描线的问题会导致错误,为什么因为,他没有涉及到[a,a + 1],在扫描线中会出现[a,a + 1]中的数据,而常用的线段树的区间概念是无法解决这样的问题的,出现了所谓的区间缺失,怎样解决,下面的代码给出了解决方案,这里简单的提一下,就是利用[ , ),这个区间性质,左闭右开,即可解决区间缺失问题

#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>using namespace std;typedef long long LL;#define lson rt << 1, l, mid#define rson rt << 1|1, mid + 1, rconst int MAXN = 2000 + 5;int  Col[MAXN << 2], n, cnt, res;double X[MAXN << 2], Sum[MAXN << 2];struct seg {    double l,r,h;    int s;    seg() {}    seg(double l,double r,double h,int s):l(l),r(r),h(h),s(s) {}    bool operator < (const seg & object) const {        return h < object.h;    }} S[MAXN];void pushup(int rt,int l,int r) {    if (Col[rt]) Sum[rt] = X[r+1] - X[l];//利用[ , ),这个区间性质,左闭右开    else if (l == r) Sum[rt] = 0;    else Sum[rt] = Sum[rt<<1] + Sum[rt<<1|1];}void update(int L, int R, int c,int rt,int l, int r) {    if(L <= l && r <= R) {        Col[rt] += c;        pushup(rt,l,r);        return ;    }    int mid = (l + r) >> 1;    if(L <= mid) update(L, R, c, lson);    if(R > mid) update(L, R, c, rson);    pushup(rt,l,r);}int binary_find(double x){    int lb = -1,ub = res - 1;    while(ub - lb > 1){        int mid = (lb + ub) >> 1;        if(X[mid] >= x) ub = mid;        else lb = mid;    }    return ub;}int main() {    int cas = 1;    while(~ scanf("%d", &n), n) {        cnt = res = 0;        for(int i = 0 ; i < n; i ++) {            double a,b,c,d;            scanf("%lf%lf%lf%lf",&a, &b, &c,&d);            S[cnt] = seg(a, c, b, 1);            X[cnt ++] = a;            S[cnt] = seg(a, c, d, -1);            X[cnt ++] = c;        }        sort(X, X + cnt);        sort(S, S + cnt);        res ++;        for(int i = 1; i < cnt; i ++) {            if(X[i] != X[i - 1]) X[res ++] = X[i];        }        memset(Sum, 0, sizeof(Sum));        memset(Col, 0, sizeof(Col));        double ans = 0;        for(int i = 0;i < cnt - 1;i ++){            int l = binary_find(S[i].l);            int r = binary_find(S[i].r) - 1;//利用[ , ),这个区间性质,左闭右开            update(l, r, S[i].s, 1, 0, res - 1);            ans += Sum[1] * (S[i + 1].h - S[i].h);        }        printf("Test case #%d\nTotal explored area: %.2lf\n\n",cas++ , ans);    }    return 0;}
原创粉丝点击