矩形面积并 HDU1542

扫描线+线段树维护(每个节点所在的区间被覆盖的次数,和被覆盖的长度的和)

线段树[l,r]表示 d1(r)1d1(l)f(x)dx , f(x)=1(当且仅当x位置被覆盖),d(x)表示x离散化的映射。

#include
using namespace std;

template  
struct Discretization {
    #define BUF_SIZE 2005
    //using dtype = int;
    T buf[BUF_SIZE];
    int tot;
    Discretization() {
        tot = 0;
    }
    void insert(T a) {
        buf[tot++] = a;
    }
    void discretization() {
        sort(buf, buf + tot);
        tot = unique(buf, buf+tot) - buf;
    }
    int get(T a) {
        int pos = lower_bound(buf, buf + tot, a) - buf;
        return pos < tot && buf[pos] == a ? pos: -1;
    }
    #undef BUF_SIZE
};
Discretization dst;

template
struct SegTree { //Seg[l,r] = Sum(d(l), d(r+1)) 即query(1,1)代表区间[buf[1],buf[2]]覆盖的线段长度
    #define TREE_SIZE 2005
    struct node {
        int l, r, cnt;
        T sum;
    } a[TREE_SIZE << 2];
    void pushup(int pos) {
        if(a[pos].cnt)  {
            a[pos].sum = dst.buf[a[pos].r] - dst.buf[a[pos].l-1];
            //printf("???? %f\n",a[pos].sum);
        }
        else a[pos].sum = a[pos << 1].sum + a[(pos << 1) ^ 1].sum;
    }
    void build(int l, int r, int pos = 1) {
        a[pos].l = l;
        a[pos].r = r;
        a[pos].sum = a[pos].cnt = 0;
        if(l != r) {
            int mid = (l + r) >> 1;
            build(l, mid, pos << 1);
            build(mid + 1, r, (pos << 1) ^ 1);
        }
    }
    void insert(int l, int r, int v, int pos = 1) {
        if(a[pos].l == l && a[pos].r == r) {
            a[pos].cnt += v;
            pushup(pos);
            return;
        }
        int mid = (a[pos].l + a[pos].r) >> 1;
        if(r <= mid) insert(l, r, v, pos << 1);
        else if(l > mid) insert(l, r, v, (pos << 1) ^ 1);
        else {
            insert(l, mid, v, pos << 1);
            insert(mid + 1, r, v, (pos << 1) ^ 1);
        }
        pushup(pos);
    }
    #undef TREE_SIZE
};
SegTree st;

struct Segment {
    double l, r, pos;
    int v;
    bool operator < (const Segment &s) const {
        return pos < s.pos;
    }
};
Segment seg[2005];

int main ()  
{  
    int n;
    int cs = 1;
    while(~scanf("%d",&n) && n) {
        int tot = 0;
        dst.tot = 0;
        while(n--) {
            double x1, y1, x2, y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            dst.insert(x1);
            dst.insert(x2);
            dst.insert(y1);
            dst.insert(y2);
            seg[tot++] = (Segment){y1,y2,x1,1};
            seg[tot++] = (Segment){y1,y2,x2,-1};
        }
        sort(seg, seg + tot);
        dst.discretization();
        st.build(1, dst.tot);
        int i = 0;
        double res = 0;
        while(i < tot) {
            double pos = seg[i].pos;
            for(;i < tot && seg[i].pos == pos;i++) {
                int l = dst.get(seg[i].l), r = dst.get(seg[i].r);
                //printf("insert l=%f r=%f v=%d\n",seg[i].l,seg[i].r,seg[i].v);
                st.insert(l+1, r, seg[i].v);
            }
            //printf("pos=%f sum=%f\n",pos,st.a[1].sum);
            if(i < tot) res += st.a[1].sum * (seg[i].pos - pos);
        }
        printf("Test case #%d\nTotal explored area: %.2f\n\n",cs++,res);
    }
    return 0;  
} 

你可能感兴趣的:(线段树)