亚特兰蒂斯

题目链接

题意:给n个矩形到一个平面上,求他们的总面积。

思路:将他们的x坐标从小到大排序,然后根据对于当前x坐标而言他们的y坐标区间进行相应的维护某些变化,这种解题思路就是扫描线。对于这题,我们要维护的是y区间的覆盖情况。

然后用覆盖的总长度去乘以当前两个x之间的距离,再全部加起来就是答案。对于如何去计算每一个x后的y区间覆盖情况,我们可以令(x1,y1,y2,1)表示左区间,(x2,y1,y2,-1)为右区间。因为

去累加的时候相当于在x2后面的就没覆盖到了。也就是说只有x1~x2的[y1,y2]区间被覆盖,还要维护个cnt表示被覆盖的次数。因为数据太大且为double记得离散化。

 

#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<cstdio>
#include<cmath>
#define ll long long
#define lowbit(x) x&(-x)
using namespace std;
const int N=1000+10;
struct node{
    double x,y1,y2;
    int val;
    node() {}
    node(double x, double y1, double y2,int val){
        this->x = x; this->val = val;
        this->y1 = y1; this->y2 = y2;
    }
    bool operator <(const node &t)const {
        return x<t.x;
    }
};
struct Tree
{
    int l;
    int r;
    double len;
    int cnt;
 } t[N*2];
vector<node> a;
vector<double> y;
int n;
void pushup(int p)
{
    int l=t[p].l;
    int r=t[p].r;
    if(t[p].cnt>0)
    {
        t[p].len=y[r+1]-y[l];
    }
    else
    {
        t[p].len=t[p<<1].len+t[p<<1|1].len;
    }
    
}
void build(int p,int l,int r)
{
    t[p].l=l;
    t[p].r=r;
    t[p].cnt=t[p].len=0;
    if(l==r)
    return;
    int mid=(l+r)>>1;
    build(p<<1,l,mid);
    build(p<<1|1,mid+1,r);
}
void update(int p,int l,int r,int val)
{
    if(t[p].l>=l&&t[p].r<=r)
    {
        t[p].cnt+=val;
        pushup(p);
        return;
    }
    int mid=(t[p].l+t[p].r)>>1;
    if(l<=mid)
    update(p<<1,l,r,val);
    if(r>mid)
    update(p<<1|1,l,r,val);
    pushup(p);
}
int main()
{
    int k=1;
    while(~scanf("%d",&n)) 
    {
        if(n==0)
        break;
        y.clear();
        a.clear();
        for(int i=0;i<n;i++)
        {
            double x1,x2,y1,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            y.push_back(y1);
            y.push_back(y2);
            a.push_back(node(x1,y2,y1,1));
            a.push_back(node(x2,y2,y1,-1));
        }
        y.push_back(-1);
        sort(a.begin(),a.end());
        sort(y.begin(),y.end());
        y.erase(unique(y.begin(),y.end()),y.end());
        int m=y.size(),num=a.size();
        build(1,0,m);
        double ans = 0.0;
        for(int i=0;i<num;i++)
        {
            int l=lower_bound(y.begin(),y.end(),a[i].y2)-y.begin();
            int r=lower_bound(y.begin(),y.end(),a[i].y1) - y.begin()-1;
            update(1,l,r,a[i].val);
            ans+=t[1].len*(a[i+1].x-a[i].x);
        }
        printf("Test case #%d\n",k++);
        printf("Total explored area: %.2lf\n\n",ans);
    }
    return 0;
 } 

 

posted @ 2019-08-17 15:40  Ldler  Views(162)  Comments(0Edit  收藏  举报