zoukankan      html  css  js  c++  java
  • hdu1542线段树(扫描线+离散化)

    题目链接

    要求矩形的面积并

    代码不复杂,主要要理解扫描线的思想以及一些细节的处理。

    首先需要将接收到的x坐标离散化,方法就是排序去重。接下来的线段树建立在这个

    关于x坐标的数组上,这很关键。线段树的节点代表一段区间,这个区间是由x坐标数组的下标

    来构成的。更新的时候就根据水平线段的左右x坐标获得区间,然后更新区间。

    看了这么多,离散化之后关于r+1,r-1的问题还是很模糊。

    我尽力理解一下,有一个[0,4]的区间,叶节点分别为[0,0],[1,1],[2,2],[3,3],[4,4],

    那么[0,0]节点表示的是区间[0,1];[1,1]节点表示的区间[1,2];[2,2]节点表示的区间[2,3];[3,3]节点表示区间[3,4];

    当向上传递时[0,1]节点表示区间[0,2],以此类推

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int maxn=110;//最多矩形个数
    struct seg{
        double lx,rx,y;
        short f;
        seg(){}
        seg(double lx_,double rx_,double y_,short f_):lx(lx_),rx(rx_),y(y_),f(f_){}
        bool operator <(const seg &a)const 
        {
                return y<a.y;
        }
    };
    int sgsNum;
    seg sgs[maxn*2];
    int x2nNum;
    //x2n
    double x2n[maxn*2];
    double len[maxn*8];
    int num[maxn*8];
    void build(int root,int l,int r)
    {
        len[root]=num[root]=0;
        if(l==r)return;
        int mid=(l+r)/2;
        build(root*2,l,mid);
        build(root*2+1,mid+1,r);
    }
    void pushUp(int root,int l,int r)
    {
        if(num[root]){
            len[root]=x2n[r+1]-x2n[l];
        }else if(l==r){
            len[root]=0;
        }
        else {
            len[root]=len[root*2]+len[root*2+1];
        }
    }
    void update(int root,int L,int R,int f,int l,int r)
    {
        if(L<=l&&r<=R){
            num[root]+=f;
            pushUp(root,l,r);
            return;
        }
        int mid=l+(r-l)/2;
        if(L<=mid)update(root*2,L,R,f,l,mid);
        if(mid<R)update(root*2+1,L,R,f,mid+1,r);
        pushUp(root,l,r);
    }
    int bin(double k)
    {
        int m,l=0,r=x2nNum-1;
        while(l<=r){
            m=(l+r)/2;
            if(x2n[m]==k)return m;
            else if(x2n[m]>k)r=m-1;
            else l=m+1;
        }
        return -1;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        int n,p=0;
        while(scanf("%d",&n)!=EOF&&n!=0){
            sgsNum=0,x2nNum=0;
            p++;
            for(int i=0;i<n;i++){
                double lx,ly,rx,ry;
                scanf("%lf%lf%lf%lf",&lx,&ly,&rx,&ry);
                sgs[sgsNum++]=seg(lx,rx,ly,1);
                sgs[sgsNum++]=seg(lx,rx,ry,-1);
                x2n[x2nNum++]=lx;
                x2n[x2nNum++]=rx;
            }
            double area=0;
            sort(x2n,x2n+x2nNum);
            sort(sgs,sgs+sgsNum);
            x2nNum=unique(x2n,x2n+x2nNum)-x2n;
            build(1,0,x2nNum-1);
            for(int i=0;i<sgsNum-1;i++){
                int l=bin(sgs[i].lx);
                int r=bin(sgs[i].rx)-1;
                update(1,l,r,sgs[i].f,0,x2nNum-1);
                area+=len[1]*(sgs[i+1].y-sgs[i].y);
            }
            printf("Test case #%d
    ",p);
            printf("Total explored area: %.2lf
    
    ",area);
        }
        //while(1);
    }

    参考资料

    http://www.cnblogs.com/zhangmingcheng/p/3907072.html

    http://blog.csdn.net/qq_37497322/article/details/75126251

  • 相关阅读:
    poj 3122 (二分查找)
    poj 1064 (二分+控制精度) && hdu 1551
    hdu 2199 (二分)
    hdu 2141 (二分)
    poj 2954 Triangle(Pick定理)
    poj 1265 Area (Pick定理+求面积)
    hdu 4946 Just a Joke(数学+物理)
    zoj 1199 几何公式推导
    MMORGP大型游戏设计与开发(客户端架构 part13 of vegine)
    MMORPG大型游戏设计与开发(客户端架构 part12 of vegine)
  • 原文地址:https://www.cnblogs.com/MalcolmMeng/p/8454230.html
Copyright © 2011-2022 走看看