1. 程式人生 > >Atlantis POJ-1151——線段樹+掃描線+坐標離散化

Atlantis POJ-1151——線段樹+掃描線+坐標離散化

mem scan http 線段樹 掃描 mar har rec 矩形

題目鏈接:

http://poj.org/problem?id=1151


題意:

求矩形並集的面積

思路:

想象一條豎線從最左邊掃描到最右邊,豎線上被矩形覆蓋的地方可以確定,即可計算出被覆蓋長度。

用線段樹維護豎線上被覆蓋的長度。

代碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn=100;

struct Rec
{
    double x1,y1,x2,y2;
};

struct Line
{
    bool operator<(const Line &t)const{return x<t.x;}
    double x;
    int y1,y2,c;
};

int n,cy,cl;
double y[maxn*2];

Rec rec[maxn];
Line line[maxn*2];

int dat[maxn*2*4];
double sum[maxn*2*4];

void change(int c,int a,int b,int k,int l,int r)
{
    if(a<=l&&b>=r)
    {
        dat[k]+=c;
        if(dat[k]==0)
        {
            if(r-l==1)
                sum[k]=0;
            else sum[k]=sum[2*k+1]+sum[2*k+2];
        }
        else sum[k]=y[r]-y[l];
    }
    else
    {
        int m=(l+r)>>1;
        if(a<m)change(c,a,b,2*k+1,l,m);
        if(b>m)change(c,a,b,2*k+2,m,r);
        if(dat[k]==0)
            sum[k]=sum[2*k+1]+sum[2*k+2];
    }
}

void discrete()//離散化
{
    sort(y,y+cy);
    cy=unique(y,y+cy)-y;
}


int main()
{
    int k=0;
    while(scanf("%d",&n)&&n)
    {
        cy=0;
        for(int i=0;i<n;++i)
        {
            scanf("%lf%lf%lf%lf",&rec[i].x1,&rec[i].y1,&rec[i].x2,&rec[i].y2);
            y[cy++]=rec[i].y1;
            y[cy++]=rec[i].y2;
        }
        discrete();

        cl=0;
        for(int i=0;i<n;++i)
        {
            line[cl].x=rec[i].x1;
            line[cl].y1=lower_bound(y,y+cy,rec[i].y1)-y;
            line[cl].y2=lower_bound(y,y+cy,rec[i].y2)-y;;
            line[cl++].c=1;

            line[cl].x=rec[i].x2;
            line[cl].y1=lower_bound(y,y+cy,rec[i].y1)-y;
            line[cl].y2=lower_bound(y,y+cy,rec[i].y2)-y;;
            line[cl++].c=-1;
        }
        sort(line,line+cl);

        memset(dat,0,sizeof(dat));
        memset(sum,0,sizeof(sum));

        double ans=0;

        change(line[0].c,line[0].y1,line[0].y2,0,0,cy);
        double pre=line[0].x;

        for(int i=1;i<cl;++i)
        {
            ans+=(line[i].x-pre)*sum[0];
            change(line[i].c,line[i].y1,line[i].y2,0,0,cy);
            pre=line[i].x;
        }

        printf("Test case #%d\nTotal explored area: %.2f\n\n",++k,ans);
    }

    return 0;
}

  

Atlantis POJ-1151——線段樹+掃描線+坐標離散化