POJ1151 Atlantis

扫描线的做法。
先对x坐标离散化,对离散化后的数组用线段树维护当前的边长。
最后要考虑到,线段树递归后的合并会出现两段之间的空缺,要把每个点和他到右面邻点的距离看成是一个点。

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100010
struct seg{
    double l,r,h;
    int f;
    bool operator < (const seg &a)const{
        return h<a.h;
    }
}t[N];
struct tree{
    int cnt;
    double len;
}e[N<<2];
double X[N];
int q=1;

void pushdown(int l,int r,int rt){
    if(e[rt].cnt)
        e[rt].len=X[r+1]-X[l];
    else if(l==r)
        e[rt].len=0;
    else
        e[rt].len=e[rt<<1].len+e[rt<<1|1].len;
}

void update(int L,int R,int l,int r,int rt,int val){
    if(L<=l&&r<=R){
        e[rt].cnt+=val;
        pushdown(l,r,rt);
        return ;
    }
    int m=l+r>>1;
    if(L<=m) update(L,R,l,m,rt<<1,val);
    if(R>m) update(L,R,m+1,r,rt<<1|1,val);
    pushdown(l,r,rt);
}

int main()
{
    int n;
    double a,b,c,d;
    while(cin>>n,n){
        memset(t,0,sizeof(t));
        int num=0;
        for(int i=0;i<n;i++){
            cin>>a>>b>>c>>d;
            X[num]=a;
            t[num++]={a,c,b,1};
            X[num]=c;
            t[num++]={a,c,d,-1};
        }
        sort(X,X+num);//离散化x坐标
        sort(t,t+num);
        int m=unique(X,X+num)-X;
        double ans=0;
        for(int i=0;i<num;i++){
            int l=lower_bound(X,X+m,t[i].l)-X;
            int r=lower_bound(X,X+m,t[i].r)-X-1;//当前x的区间l->r
            update(l,r,0,m,1,t[i].f);//向0->m的线段树上插入l->r的t[i].f
            ans+=e[1].len*(t[i+1].h-t[i].h);//底乘高
        }
        printf("Test case #%d\nTotal explored area: %.2lf\n\n",q++,ans);
    }
    return 0;
}
发布了38 篇原创文章 · 获赞 5 · 访问量 849

猜你喜欢

转载自blog.csdn.net/Fooooooo/article/details/104118489