hdu 1542 Atlantis 面积并 线段树 扫描线

转自这里

 

#include<cstdio>
#include<algorithm>
#include<cstring>
#define LMT 202
#define left l,m,x<<1
#define right m+1,r,x<<1|1
using namespace std;
//shit double int 搞错了
struct line
{
    double h,l,r;
    int d;
    line(void){}
    line(double y,double x1,double x2,int dd):h(y),l(x1),r(x2),d(dd){}
    bool operator<(const line &y)const
    {
        return h<y.h;
    }
}ln[LMT];
double sum[LMT<<2],X[LMT];
int cnt[LMT<<2];
void pushup(int l,int r,int x)//计算在这个纵坐标值的范围内,横轴的总长度
{
    if(cnt[x])sum[x]=X[r+1]-X[l];//这里可以防止漏选区域,看两个一大一小的矩阵合在一起的情况
    else if(l==r)sum[x]=0;
    else sum[x]=sum[x<<1]+sum[x<<1|1];
    /*****
    这里道出了了用l,r-1的原因,如果是l,r,那么请计算一下只有一个矩阵的情况,这里
    不会出现l==r的情况,会继续计算sum[x<<1],虽然一般来说值是对的,可是这是不符合程序
    定义的,不严谨,而且很可能值也会错,对了,重叠情况也要考虑
    *****/
}
void update(int L,int R,int c,int l,int r,int x)
{
    if(L<=l&&r<=R)
    {
        cnt[x]+=c;
        pushup(l,r,x);
        return;
    }
    int m=(l+r)>>1;
    if(L<=m)update(L,R,c,left);
    if(R>m)update(L,R,c,right);
    pushup(l,r,x);
}
int equry(double key,int n)//二分查找
{
    int m,l=0,r=n;
    while(l<=r)
    {
        m=(l+r)>>1;
        if(key==X[m])return m;
        if(key>X[m])l=m+1;
        else r=m-1;
    }
    return -1;
}
int main(void)
{
    int n,k,I=1;
    double ans;
    while(~scanf("%d",&n)&&n>0)
    {
        double a,b,c,d;
        int num=0;
        ans=0;
        while(n--)
        {
           scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
           ln[num]=line(b,a,c,1);
           X[num]=a;
           num++;
           ln[num]=line(d,a,c,-1);
           X[num]=c;
           num++;
        }
        sort(ln,ln+num);
        sort(X,X+num);
        memset(sum,0,sizeof(sum));
        memset(cnt,0,sizeof(cnt));
        k=1;
        for(int i=1;i<num;i++)
        if(X[i]!=X[i-1])X[k++]=X[i];
        for(int i=0;i<num-1;i++)
        {
            int l=equry(ln[i].l,k-1),r=equry(ln[i].r,k-1)-1;
            if(l<=r)//原代码此处有事
            {
              update(l,r,ln[i].d,0,k-1,1);//可能有重叠情况
              ans+=sum[1]*(ln[i+1].h-ln[i].h);
            }
        }
        printf("Test case #%d\nTotal explored area: %.2lf\n\n",I++,ans);
    }
    return 0;
}

你可能感兴趣的:(hdu 1542 Atlantis 面积并 线段树 扫描线)