zoukankan      html  css  js  c++  java
  • HDU 1542 Atlantis

    题目链接:HDU-1542

    题意为给定许多个矩形,求面积的并。

    基本的思路是首先把所有矩形按照下边高度从下往上排序,然后依次计算每两条边(上下边)之间夹的面积大小。

    如图,每条绿色的线叫做扫描线。我们想要做到的事情是每次求出两条扫描线间的面积,如图中序号。显然,假设有n个矩形,则有2n条扫描线,我们需要求2n-1次面积。

    要求面积,我们需要知道两条扫描线之间的高(很容易求)和当前扫描线扫描到的长度。

    如图,即需要求出蓝色线段的长度。

    我们首先把所有横坐标离散化,以此建立一棵线段树,线段树的每个节点表示离散化后的一个最小区间(即一个坐标到右边第一个坐标之间的区间)。我们用线段树维护每个区间被几条矩形的底边的投影所覆盖。同时利用这个信息,维护每个区间被覆盖的长度。

    维护每个区间被几条矩形的底边的投影所覆盖,就等同于区间add的操作。每次扫到一个底边,就在底边对应的区间+1,若扫到一个顶边,则对应区间-1。这个操作是本题的核心所在,请仔细理解!

    在每次更新“每个区间被几条矩形的底边的投影所覆盖”的mark值的同时,我们用如下方式维护每个区间被覆盖的长度sum。

        if(mark[o]) sum[o]=(dict[r+1]-dict[l]);
        else if(l==r) sum[o]=0;
        else sum[o]=sum[o*2]+sum[o*2+1];
    

    即若当前区间被完整覆盖(和被几条边覆盖无关),则sum等于区间对应长度。否则,sum等于两个自区间被覆盖的长度之和。

    所以每次扫描完,只需在答案上加上sum[1]*h即可。

    非常类似的题目还有HDU-1828

    代码如下:

    #include<cstdio>
    #include<set>
    #include<map>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    
    const int MAXN=2010;
    struct Line
    {
        int x1,x2,d;
        double y;
        bool operator < (Line x)
        {
            return y<x.y;
        }
        void operator = (Line x)
        {
            x1=x.x1;
            x2=x.x2;
            y=x.y;
            d=x.d;
        }
    };
    double dict[MAXN];
    map<double,int> index;
    double xx1[MAXN],xx2[MAXN],yy1[MAXN],yy2[MAXN];
    set<double> S;
    Line lines[MAXN];
    
    LL mark[MAXN<<2];
    double sum[MAXN<<2];
    void modify(LL o,LL l,LL r,LL ml,LL mr,LL num)
    {
        if(ml<=l && r<=mr)
        {
            mark[o]+=num;
            if(mark[o]) sum[o]=(dict[r+1]-dict[l]);
            else if(l==r) sum[o]=0;
            else sum[o]=sum[o*2]+sum[o*2+1];
        }
        else
        {
            LL m=(r-l)/2+l;
            if(ml<=m) modify(o*2,l,m,ml,mr,num);
            if(mr>m) modify(o*2+1,m+1,r,ml,mr,num);
            if(mark[o]) sum[o]=(dict[r+1]-dict[l]);
            else if(l==r) sum[o]=0;
            else sum[o]=sum[o*2]+sum[o*2+1];
        }
    }
    int main()
    {
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif
        int n,t=0;
        while(scanf("%d",&n)!=EOF && n)
        {
            int dictnum=0;
            index.clear();
            S.clear();
            memset(sum,0,sizeof(sum));
            memset(mark,0,sizeof(mark));
            double ans=0;
            printf("Test case #%d
    ",++t);
            for(int i=1;i<=n;i++)
            {
                scanf("%lf%lf%lf%lf",&xx1[i],&yy1[i],&xx2[i],&yy2[i]);
                S.insert(xx1[i]);
                S.insert(xx2[i]);
            }
            for(set<double>::iterator it=S.begin();it!=S.end();it++)
            {
                dict[++dictnum]=*it;
                index[*it]=dictnum;
            }
            for(int i=1;i<=n;i++)
            {
                Line tmp;
                tmp.x1=index[xx1[i]]; tmp.x2=index[xx2[i]];
                tmp.y=yy1[i]; tmp.d=1;
                lines[2*i-1]=tmp;
                tmp.y=yy2[i]; tmp.d=-1;
                lines[2*i]=tmp;
            }
            sort(lines+1,lines+1+2*n);
            for(int now=1;now<=n*2-1;now++)
            {
                double h=lines[now+1].y-lines[now].y;
                Line ing=lines[now];
                modify(1,1,dictnum-1,ing.x1,ing.x2-1,ing.d);
                ans+=h*sum[1];
                //printf("%.2lf %.2lf %.2lf %.2lf
    ",dict[ing.x1],dict[ing.x2],ing.y,ans);
            }
            printf("Total explored area: %.2lf
    
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本
    C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本
    C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本
    C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本
    《程序员,你伤不起》 回答热心爸爸读者的疑问
    入驻微信公众号平台【今日热点在线】、【大数据躺过的坑】和【九哥九嫂小日子】,欢迎关注
    入驻百家号【九哥聊IT】和【九哥九嫂小日子】,欢迎关注
    全网最详细的最新稳定OSSEC搭建部署(ossec-server(CentOS7.X)和ossec-agent(CentOS7.X))(图文详解)
    CentOS 7的安装详解
    全网最全的Windows下Anaconda2 / Anaconda3里正确下载安装爬虫框架Scrapy(离线方式和在线方式)(图文详解)
  • 原文地址:https://www.cnblogs.com/zarth/p/6378085.html
Copyright © 2011-2022 走看看