POJ1151-Atlantis【线段树,扫描线,离散化】

正题

题目链接:http://poj.org/problem?id=1151


题目大意

有n个矩形,求所以矩形的覆盖面积。


解题思路

我们用离散化一个坐标,然后每次用线段树维护这个宽度内覆盖高度和,然后定义左上的点是加入,右下的点是弹出。


code

#include
#include
#include
#define N 110
using namespace std;
struct treenode{
    int l,r;
    double mark,val;
}t[N*8];
struct node{
    double x1,x2,y;
    int flag;
}a[N*2];
int n,tot,l;
double x[N*2],ans;
void build(int k,int l,int r)
{
    t[k].l=l;t[k].r=r;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(k*2,l,mid);
    build(k*2+1,mid+1,r);
}
void change(int k,int l,int r,int num)
{
    if(t[k].l==l&&t[k].r==r)
    {
        t[k].mark+=num;//标记了多少次
        if(t[k].mark)t[k].val=x[t[k].r+1]-x[t[k].l];//如果标记就直接返回答案
        else if(l==r) t[k].val=0;
        else t[k].val=t[k*2].val+t[k*2+1].val;//合并下面
        return;
    }
    int mid=(t[k].l+t[k].r)>>1;
    if(r<=mid) change(k*2,l,r,num);
    else if(l>mid) change(k*2+1,l,r,num);
    else change(k*2,l,mid,num),change(k*2+1,mid+1,r,num);
    if(t[k].mark)t[k].val=x[t[k].r+1]-x[t[k].l];
    else t[k].val=t[k*2].val+t[k*2+1].val;
}
bool cmp(node x,node y)
{return x.yint main()
{
    while(scanf("%d",&n)&&n)
    {
        memset(t,0,sizeof(t));
        ans=0;int cnt=0,l=0;
        double x1,y1,x2,y2;
        for(int i=1;i<=n;i++)
        {
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            x[++l]=x1;x[++l]=x2;
            a[++cnt]=(node){x1,x2,y1,1};
            a[++cnt]=(node){x1,x2,y2,-1};
        }
        stable_sort(x+1,x+l+1);
        l=unique(x+1,x+l+1)-(x+1);//离散化
        build(1,1,l);//建树
        stable_sort(a+1,a+1+cnt,cmp);
        for(int i=1;iint xx=lower_bound(x+1,x+l,a[i].x1)-x;
            int yy=lower_bound(x+1,x+l,a[i].x2)-x-1;//找到位置
            change(1,xx,yy,a[i].flag);//修改
            ans+=t[1].val*(a[i+1].y-a[i].y);//计算该宽度答案
        }
        printf("Test case #%d\nTotal explored area: %.2f\n\n",++tot,ans);
    }
}

你可能感兴趣的:(数据结构)