zoukankan      html  css  js  c++  java
  • POJ 1151 Atlantis

    线段树+扫描线

    矩形面积并

    之前写过矩形周长并

    还是跟矩形周长并一样,将每一个矩形的横边和竖边处理出来

    用竖边将整个平面分成若干个区间

    用线段树维护这些区间被覆盖的长度

    再用一条扫描线不断从下往上扫描,扫描横边

    当扫描到一个矩形的下边时,将这一段区间在线段树上覆盖掉,更新信息

    当扫描到一个矩形的上边时,将这一段区间的覆盖去掉即可

    那么只有统计答案时与矩形周长并不同

    答案就是当前整个区间被覆盖的长度*两次扫描线的高度之差

    #include <iostream>
    #include <algorithm>
    #include <map>
    #include <cstdio>
    #define inf (int)1e9
    using namespace std;
    int n,w,last,tot,k;
    double c[10000],ans;
    double s[10000];
    map <double,int> id;
    struct node
    {
        double a,b,c,d;
    }p[5100];
    struct tree
    {
        int l,r,sum;
        double len;
    }sh[100000];
    struct edge
    {
        int l,r,kind;
        double num;
    }a[11000];
    bool cmp(edge a,edge b)
    {
        return (a.num<b.num || (a.num==b.num && a.kind>b.kind));
    }
    void pushup(int x)
    {
        if (sh[x].sum>0)
          sh[x].len=c[sh[x].r+1]-c[sh[x].l];//完全覆盖
        else
        if (sh[x].l==sh[x].r)
          sh[x].len=0;//叶子结点
        else
          sh[x].len=sh[x+x].len+sh[x+x+1].len;//一般情况
    }
    void build(int x,int ll,int rr)
    {
        sh[x].l=ll;
        sh[x].r=rr;
        sh[x].sum=0;
        sh[x].len=0;
        if (ll==rr)
          return;
        int mid;
        mid=(ll+rr)>>1;
        build(x+x,ll,mid);
        build(x+x+1,mid+1,rr);
    }
    void change(int x,int ll,int rr,int v)
    {
        if (sh[x].l>=ll && sh[x].r<=rr)
        {
            sh[x].sum+=v;
            pushup(x);
            return;
        }
        int mid;
        mid=(sh[x].l+sh[x].r)>>1;
        if (ll<=mid)
          change(x+x,ll,rr,v);
        if (rr>mid)
          change(x+x+1,ll,rr,v);
        pushup(x);
    }
    int main()
    {
        while (1)
        {
            tot++;
            scanf("%d",&n);
            if (n==0)
              break;
            for (int i=1;i<=n;i++)
              scanf("%lf%lf%lf%lf",&p[i].a,&p[i].b,&p[i].c,&p[i].d);
            k=0;
            for (int i=1;i<=n;i++)
            {
                k++;
                s[k]=p[i].a;
                k++;
                s[k]=p[i].c;
            }
            sort(s+1,s+1+k);
            int m=unique(s+1,s+1+k)-s-1;
            for (int i=1;i<=m;i++)
              id[s[i]]=i,c[i]=s[i];
             w=0;
            for (int i=1;i<=n;i++)//处理扫描线
            {
                w++;
                a[w].l=id[p[i].a];a[w].r=id[p[i].c];
                a[w].num=p[i].b;a[w].kind=1;
                w++;
                a[w].l=id[p[i].a];a[w].r=id[p[i].c];
                a[w].num=p[i].d;a[w].kind=-1;
            }
            build(1,0,m+1);
            sort(a+1,a+1+w,cmp);
            ans=0;
            for (int i=1;i<=w;i++)
            {
                change(1,a[i].l,a[i].r-1,a[i].kind);
                if (i==w)
                  break;
                ans+=(a[i+1].num-a[i].num)*sh[1].len;//统计答案
            }
            printf("Test case #%d
    ",tot);
            printf("Total explored area: %.2f
    
    ",ans);
        }
    }
  • 相关阅读:
    2020.9.26
    2020.10.2
    判断方法
    sql与include
    File类的获取方法
    【每日日报】第十五天
    【每日日报】第十三天
    【每日日报】第十四天
    两数相加(输入框)
    判断闰年
  • 原文地址:https://www.cnblogs.com/huangchenyan/p/11331648.html
Copyright © 2011-2022 走看看