扫描线,线段树,离散化——HDU - 1542

题目含义

每一行给出两个点,代表一个矩形的左下角端点和右上角端点

要你求出这些矩形覆盖坐标轴的整个面积

题目分析

用平行x轴的扫描线扫描整个图形,得到很多长宽不同的矩形,求出面积再相加

将每个矩形的面积记作 len(x)*len(y)

每个len(x)我们通过加减每个点的x左右坐标,通过线段树求sum[1]得到

每个len(y)我们通过这个点与下一个点的y坐标的差得到

所以我们要把所有点按y轴大小排序,并且记录每个点的左右x轴坐标

注意:这里用的线段树sum【l,r】不是指区间【l,r】的和,而是指X.l和X.r的差

题目代码

#include<stdio.h>
#include<iostream>
#include<vector>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=1e5+7;
typedef long long LL;
vector<double>v;
int n;
double x1,y1,x2,y2;
double len[maxn<<2];
int cov[maxn<<2];
struct node{
    double y,x1,x2;
    int k;
}rem[maxn];
int getid(double x){
    return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
bool cmp(node a,node b){
    return a.y<b.y;
}
void pushup(int l,int r,int rt){
    if(cov[rt]>0)len[rt]=v[r]-v[l-1];
    else if(l==r)len[rt]=0;
    else len[rt]=len[rt<<1]+len[rt<<1|1];
}
void updata(int l,int r,int rt,int ll,int rr,int k){
    if(ll<=l&&r<=rr){
        cov[rt]+=k;
        pushup(l,r,rt);
        return;
    }
    int mid=(l+r)>>1;
    if(ll<=mid)updata(l,mid,rt<<1,ll,rr,k);
    if(rr>mid)updata(mid+1,r,rt<<1|1,ll,rr,k);
    pushup(l,r,rt);
}
int main(){
    int ce=0;
    while(scanf("%d",&n)&&n){
        memset(len,0,sizeof(len));
        memset(cov,0,sizeof(cov));
        v.clear();
        int cnt=0;
        for(int i=0;i<n;i++){
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            v.push_back(x1);
            v.push_back(x2);
            rem[++cnt].x1=x1,rem[cnt].x2=x2,rem[cnt].y=y1,rem[cnt].k=1;
            rem[++cnt].x1=x1,rem[cnt].x2=x2,rem[cnt].y=y2,rem[cnt].k=-1;
        }
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        sort(rem+1,rem+1+cnt,cmp);
        double ans=0;
        for(int i=1;i<cnt;i++){
            updata(1,cnt,1,getid(rem[i].x1),getid(rem[i].x2)-1,rem[i].k);
            ans+=len[1]*(rem[i+1].y-rem[i].y);
        }
        printf("Test case #%d\nTotal explored area: %.2f\n\n",++ce,ans);
    }
    return 0;
}

 

posted @ 2019-07-22 16:22  helman78  阅读(145)  评论(0编辑  收藏  举报