您的位置:首页 > 其它

HDU1542 Atlantis(面积并)

2015-07-29 08:59 393 查看
题意:给出n个矩形的 左下角和右上角坐标,计算他们覆盖的面积。

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <string.h>
#include <map>
#include <set>
using namespace std;
#define maxn 11005
struct line
{
    double x1,x2,y1;
    int c;
    line(){}
    line(double xx1,double xx2,double yy1,int cc):
        x1(xx1),x2(xx2),y1(yy1),c(cc){}
}s[maxn];//存平行于x轴的边,同时存下一个纵坐标,用于计算竖边长度
bool clm(line x,line y)
{
    return x.y1<y.y1;
}
struct node
{
    int l,r;
    double len;//存某个区间覆盖的长度
    int c;//c==1表示的某个线段区间完全覆盖,c==0表示不完全覆盖
}tree[maxn*4];
double x[maxn];
int n;
void build(int id,int l,int r)
{
    tree[id].l=l;
    tree[id].r=r;
    tree[id].c=0;
    tree[id].len=0.0;
    if(l!=r)
    {
        int mid=(l+r)/2;
        build(id*2,l,mid);
        build(id*2+1,mid+1,r);
    }
}
void pushup(int id,int l,int r)
{
    if(tree[id].c>0)//tree[id].c>0该区间完全覆盖
        tree[id].len=x[r]-x[l-1];
    else if(l==r)tree[id].len=0.0;//在tree[id].c不大于0的情况下,l==r,自然覆盖为零
    else//另外,在tree[id].c不大于0,就是它左右儿子的长度
        tree[id].len=tree[id*2].len+tree[id*2+1].len;
}
void update(int id,int l,int r,int c)
{
    if(l==tree[id].l&&tree[id].r==r)//注意这里要恰好要等于更新的区间
    {
        tree[id].c+=c;
        pushup(id,tree[id].l,tree[id].r);
    }
    else
    {
        int mid=(tree[id].l+tree[id].r)/2;
        if(r<=mid)update(id*2,l,r,c);//如果r<=mid,说明全在左边
        else if(l>mid)update(id*2+1,l,r,c);//如果l>mid,说明全在右边
        else
        {
            //这种情况就是左右边都有
            update(id*2,l,mid,c);//我们更新的是l~mid
            update(id*2+1,mid+1,r,c);//mid+1~r
        }
        pushup(id,tree[id].l,tree[id].r);
    }
}

int main()
{
      int i,k;
      double x1,x2,y1,y2;
      int tt=1;
      while(cin>>n&&n)
      {
          k=0;
          for(i=0;i<n;i++)
          {
              cin>>x1>>y1>>x2>>y2;
              s[k]=line(x1,x2,y1,1);
              x[k]=x1;
              k++;
              s[k]=line(x1,x2,y2,-1);
              x[k]=x2;
              k++;
          }
          sort(s,s+k,clm);//x的边按照高度排序
          sort(x,x+k);//x数组存的是平行于x轴每边的横坐标,用于计算横边的长度(double型)
          int m=1;
          for(i=1;i<k;i++)
          {
              if(x[i]!=x[i-1])
                x[m++]=x[i];
          }//取出重合的横坐标

          build(1,1,m-1);//按边建树
          double ans=0.0;
          for(i=0;i<k-1;i++)
          {
                int l=lower_bound(x,x+m-1,s[i].x1)-x;//查找s[i].x1,s[i].x2在x中的下标用于更新
                int r=lower_bound(x,x+m-1,s[i].x2)-x;
                update(1,l+1,r,s[i].c);
                ans+=tree[1].len*(s[i+1].y1-s[i].y1);//每次更新后覆盖的总长度为tree[1].len
                                                     //再乘以相对高度就是面积
          }
          printf("Test case #%d\n",tt++);
          printf("Total explored area: %0.2f\n",ans);
          cout<<endl;
      }

    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: