zoukankan      html  css  js  c++  java
  • POJ1389:Area of Simple Polygons——扫描线线段树题解+全套代码注释

    http://poj.org/problem?id=1389

    题面描述
    在二维xy平面中有N,1 <= N <= 1,000个矩形。矩形的四边是水平或垂直线段。矩形由左下角和右上角的点定义。每个角点都是一对两个非负整数,范围从0到50,000,表示其x和y坐标。

    求出所有矩形的面积(重叠部分只算一次)

    示例:考虑以下三个矩形:

    矩形1:<(0,0)(4,4)>,

    矩形2:<(1,1)(5,2)>,

    矩形3:<(1,1)(2,5)>。

    所有由这些矩形构造的简单多边形的总面积为18。

    输入
    输入由多个测试用例组成。一行4 -1分隔每个测试用例。一个额外的4 -1的行标志着输入的结束。在每个测试用例中,矩形都是一行一个地排列的。在矩形的每一行中,给出4个非负整数。前两个是左下角的x和y坐标。接下来的两个是右上角的x和y坐标。

    输出
    对于每个测试用例,输出所有简单多边形的总面积。

    示例输入
    0 0 4 4
    1 1 5 2
    1 1 2 5
    -1 -1 -1 -1
    0 0 2 2
    1 1 3 3
    2 2 4 4
    -1 -1 -1 -1
    -1 -1 -1 -1

    示例输出
    18
    10

    线段树的妙用之一——扫描线。

    我们先将坐标离散化(然而这题数据小,不需要)

    然后将一个矩形分成两半,存下它的下边界和上边界,并且用w记录哪个是上边界哪个是下边界。

    这里先将上边界w=-1,下边界w=1(下面说为什么)

    然后我们按照每个边界的y从小到大排序(如果y相同,先添加上界)。

    这样预处理就完成了。

    完后开始想线段树的含义。

    节点表示其区间内被覆盖的点(不算重复)的数目。

    那么我们假设一条边的长度为k,那么其覆盖的点的数量就是看k+1,于是为了方便起见,我们把边界都少存一位,这样我们就可以用这个表示边界长度了。

    然后我们一条一条添加边,等效于在线段树区间内+w。

    现在你知道为什么上边界w=-1了:标志着这个矩形结束了,就是把原来被覆盖的点撤回。

    那么显然从上一个边界到下一个边界中矩形覆盖的面积就是tree[1]*上下边界距离。

    把他们都加在一起就是答案,这样做是不是很巧妙的避免了重复面积啊(原因是被覆盖的点没有被重复计算)!

    但是这样问题就变成了如何求被覆盖的点(不算重复)的数目了。

    我们用lazy标记表示当前区间被一整条下边界完全经过,这样的边的边数。

    如果lazy>0说明该区间被完全覆盖了。

    如果lazy=0:

    如果此时l=r,直接更新为0(显然)。

    如果不是,我们就需要重新更新节点的值了,那就是他的左右儿子的节点个数和。

    (思考lazy=0只是说明了该区间没有被完全覆盖,但是它可能被非完全经过的下边界覆盖了)

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    inline int read(){
        int X=0,w=1; char ch=0;
        while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
        return X*w;
    }
    struct node{
        int y;
        int x1;
        int x2;
        int w;
    }edge[2001];
    bool cmp(node a,node b){
        return a.y<b.y;
    }
    int tree[200001];//区间被覆盖点数
    int lazy[200001];//当前区间被一整条下边界完全经过,这样的边的边数
    void build(int a,int l,int r){
        lazy[a]=0;
        if(l==r){
        tree[a]=0;
        return;
        }
        int mid=(l+r)>>1;
        build(a*2,l,mid);
        build(a*2+1,mid+1,r);
        tree[a]=tree[a*2]+tree[a*2+1];
        return;
    }
    void add(int a,int l,int r,int l1,int r1,int w){
        if(r1<l||l1>r)return;
        if(l1<=l&&r<=r1){
        lazy[a]+=w;
        if(lazy[a]>0)tree[a]=r-l+1;//完全覆盖,值为区间长 
        else if(l==r)tree[a]=0;//该点没有被覆盖,清零 
        else tree[a]=tree[a*2]+tree[a*2+1];//没有被完全覆盖,需要重新更新
        return;
        }
        int mid=(l+r)>>1;
        add(a*2,l,mid,l1,r1,w);
        add(a*2+1,mid+1,r,l1,r1,w);
        if(lazy[a]==0)tree[a]=tree[a*2]+tree[a*2+1];//没有被完全覆盖,需要重新更新
        return;
    }
    int main(){
        bool ok=0;
        while(233){
        int n=0;
        while(233){
            int a=read();
            int b=read();
            int c=read();
            int d=read();
            if(a==b&b==c&&c==d&&a==-1){
            if(!n)ok=1;
            break;
            }
            n++;
            edge[n*2-1].x1=a;
            edge[n*2-1].y=b;
            edge[n*2-1].x2=c;
            edge[n*2].y=d;
            edge[n*2-1].w=1;//到下界时加上该矩形
            edge[n*2].w=-1;//到上界时去掉该矩形
            edge[n*2].x1=edge[n*2-1].x1;
            edge[n*2].x2=edge[n*2-1].x2;
        }
        if(ok==1)break;
        sort(edge+1,edge+2*n+1,cmp);
        //根据上下界大小排序,从下往上扫描矩形 
        build(1,0,50000);
        ll h,ans=0;
        add(1,0,50000,edge[1].x1+1,edge[1].x2,edge[1].w);
        //建一个底 
        //因为是点数和,所有求长度的话要减去一个点就为长度 
        for(int i=2;i<=2*n;i++){
            h=edge[i].y-edge[i-1].y;//下一个矩形的下界(或者刚才的矩形的上界)之差即为高 
            ans+=h*tree[1];//底乘高为面积 
            add(1,0,50000,edge[i].x1+1,edge[i].x2,edge[i].w);//加上新矩形(或减去旧矩形) 
        }
        printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    UVA1627-Team them up!(二分图判断+动态规划)
    UVA10817-Headmaster's Headache(动态规划基础)
    UVA1626-Brackets sequence(动态规划基础)
    UVA11584-Partitioning by Palindromes(动态规划基础)
    UVA11584-Partitioning by Palindromes(动态规划基础)
    UVA11400-Lighting System Design(动态规划基础)
    UVA12563-Jin Ge Jin Qu hao(动态规划基础)
    UVA116-Unidirectional TSP(动态规划基础)
    JavaScriptCore框架在iOS7中的对象交互和管理
    iOS7新JavaScriptCore框架入门介绍
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/7866998.html
Copyright © 2011-2022 走看看