Line Segment Tree - Scan Line Ideas HDU_1542 Atlantis

Classical area intersection problem

Use line segment tree + scan line method


Take this example as an example

The line segment tree and scan line are combined in this way


    The line segment tree counts the length of the valid interval segment, that is, which interval segment is currently scanned by the scan line.
    For example, which segment is currently scanned, then the len in t[1] in the
    line segment tree is the length of the line segment tree. Generally In this case, it is a post-order traversal. First, update the information of the child node, and then get the information of the child node back to update itself.

    Once the line segment is canceled and the outgoing edge is encountered, then the coverage of this point will be empty, and then the information of this point will be left and right. The information statistics
    of the two children will be fed back if the left and right children still have side information at this time. If not, the line segment will be set to zero


    . In general, the line segment tree statistics are the real effective length of the current scanning period.
    How to count through the line segment tree?
    Taking the discretized abscissa as an example,
    the statistics of each leaf node of the line segment tree are all the discrete x-coordinates that have appeared from small to large. For example,
    there are four x-coordinates of 10 15 20 25. The abscissa is to use the abscissa to build a tree
    , that is, these four points correspond to the four points 0 1 2 3 respectively, and
    the line segment tree is built.
    Then every time we scan a line segment, we go to the line segment tree to update the line segment
    . mean? It is according to whether the line segment is an outgoing edge or an incoming edge.
    If it is a rectangular incoming edge, then take this line segment into the line segment tree. Haven't we already built the line segment tree according to the left side of the corresponding x?
    Then now we encounter an incoming edge according to our previous The line segment tree that needs to be maintained - "the effective width of the rectangle where the currently scanned line segment is located"
    We need to let the line segment tree understand whether the current effective width has changed
    That is to say, this becomes the starting coordinate and the ending coordinate is updated to the line segment tree,
    so that we can check the effective width of the line segment tree and then use the height to make a difference
    to know the effective area of ​​the current scanning rectangle.
    Then we take Go to the two coordinates of the current edge and update it in the line segment tree.
    If this interval segment has not been marked in the line segment tree, then
    mark it and feed it back to the parent node
    . Finally, the parent node gets the effective width in the current state.

    Then if the current edge is a Out of the border, that is, it may be necessary to reduce

    Still get the line segment tree to cancel the width

    When we traverse all the edges in the scanning direction, that is, the area of ​​each block is accumulated 

    That is to say, the area statistics complexity O(edge*logn) is realized.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 110;
struct node{
    int xx;
    double len;
    int l, r;
}t[maxn<<3];
double x[maxn<<2];
int xtot;
struct edge{
    double l,r,h;
    int xx;
    edge(){}
    edge(double a,double b,double c,int cover):l(a),r(b),h(c),xx(cover){}
    bool operator<(const edge &E){
        return h<E.h;
    }
}e[maxn<<2];
int etot;
bool cmp(int a,int b){
    return a<b;
}
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
void build(int l,int r,int rt){
    t[rt].l = l;
    t[rt].r = r;
    t[rt].xx = t[rt].len = 0;
    if(l==r)return;
    int mid = l+r>>1;
    build(lson);
    build(rson);
}
void pushup(int now){
    if(t[now].xx){
        t[now].len = x[t[now].r+1]-x[t[now].l];
    }
    else if(t[now].l==t[now].r){
        t[now].len=0;
    }
    else {
        t[now].len = t[now<<1].len+t[now<<1|1].len;
    }
}

void update(int l,int r,int rt,int val){
    if(t[rt].l==l&&t[rt].r==r){
        t[rt].xx += val;
        pushup(rt);
        return;
    }
    int mid = t[rt].l+t[rt].r>>1;//*****
    if(r<=mid)update(l,r,rt<<1,val);
    else if(l>mid)update(l,r,rt<<1|1,val);
    else{
        update(l,mid,rt<<1,val);
        update(mid+1,r,rt<<1|1,val);
    }
    pushup(rt);
}
intmain()
{
    int n,test=0;
    while(scanf("%d",&n),n){
        double x1,x2,y1,y2;
        test++;
        for(int i=1;i<=n;i++){
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            e[etot++] = edge(x1,x2,y1,1);
            e [etot ++] = edge (x1, x2, y2, -1);
            x[xtot++] = x1;
            x[xtot++] = x2;
        }
        sort (e, e + etot);
        sort(x,x+xtot);
        xtot = unique(x,x+xtot)-x;//Discretize the x coordinate
        double years =0;
        build(0,xtot-1,1);
        for(int i=0;i<etot;i++){
            int l = lower_bound(x,x+xtot,e[i].l)-x;
            int r = lower_bound(x,x+xtot,e[i].r)-x-1;
            //The interval here does not completely contain the interval query 10-15 such as 10, 15, 20, 25, then the query is 10-10
            //What does it mean because the line segment tree is still a discrete statistical structure, and the interval line segment is still queried according to the starting point
            update(l,r,1,e[i].xx);
            ans + = (e [i + 1] .he [i] .h) * t [1] .len;
        }
        printf("Test case #%d\nTotal explored area: %.2f\n\n",test,ans);
        etot = 0;
        xtot = 0;
    }
    return 0;

}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325827903&siteId=291194637