HDU1542 线扫描求矩形面积并

原题的链接为: http://acm.hdu.edu.cn/showproblem.php?pid=1542


        这道题是最简单的先扫描的例题,适合初学线扫描的认真仔细理解的一道题。其他的线扫描的题都是在这上面的加深,比如矩形面积并,周长等,思想都是一样的,只是更新部分有的差别而已。说来也就,建树,去重,最后加一条边,计算一次矩形的面积。线扫描的题最主要的就是考虑好状态的更新。吐舌头

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
#define nn 110

struct node
{
    int l,r,v;
    double len;
}tree[nn<<3];

struct seg
{
    double l,r,h;
    int f;//-1表示上边,1表示下边
}s[nn<<1];
double pos[nn<<1];

bool cmp(seg a,seg b)
{
    return a.h<b.h;
}
int binary(double c,int low,int top)//二分查找该点的离散值
{
    while(low<=top)
    {
        int mid=(low+top)>>1;
        if(pos[mid]==c)     return mid;
        else if(pos[mid]>c) top=mid;
        else low=mid+1;
    }
    return -1;
}
void build(int ll,int rr,int rt)//建树
{
    tree[rt].l=ll;  tree[rt].r=rr;  tree[rt].v=0;
    if(ll==rr)  return;
    int mid=(ll+rr)>>1;
    build(ll,mid,rt<<1);
    build(mid+1,rr,rt<<1|1);
}
void getlen(int rt)//长度更新
{
    if(tree[rt].v)//该区间被覆盖
    {
        tree[rt].len=pos[tree[rt].r+1]-pos[tree[rt].l];
    }
    else if(tree[rt].l==tree[rt].r)//更新的区间为一个区间
    {
        tree[rt].len=0;
    }
    else//更新的区间不为一个点,由他的两个儿子节点来更新他的长度
    {
        tree[rt].len=tree[rt<<1].len+tree[rt<<1|1].len;
    }
}
void updata(int ll,int rr,int c,int rt)//更新的区间查找
{
    if(tree[rt].l==ll && tree[rt].r==rr)
    {
        tree[rt].v+=c;
        getlen(rt);
        return ;
    }
    int mid=(tree[rt].l+tree[rt].r)>>1;
    if(rr<=mid)
    {
        updata(ll,rr,c,rt<<1);
    }
    else if(ll>mid)
    {
        updata(ll,rr,c,rt<<1|1);
    }
    else
    {
        updata(ll,mid,c,rt<<1);
        updata(mid+1,rr,c,rt<<1|1);
    }
    getlen(rt);
}
int main()
{
    int n,t=1;
    while(scanf("%d",&n)&&n)
    {
        int num=0;
        for(int i=0;i<n;i++)
        {
            double x1,x2,y1,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            s[num].l=x1;   s[num].r=x2;    s[num].h=y1;    s[num].f=1;
            s[num+1].l=x1;   s[num+1].r=x2;    s[num+1].h=y2;    s[num+1].f=-1;
            pos[num]=x1;   pos[num+1]=x2;
            num+=2;
        }
        sort(pos,pos+num);//离散化
        sort(s,s+num,cmp);
        int m=1;
        for(int i=1;i<num;i++)//去重
        {
            if(pos[i]!=pos[i-1])
            pos[m++]=pos[i];
        }
        build(0,m-1,1);

        double ans=0;//记录面积
        for(int i=0;i<num;i++)
        {

            int l=binary(s[i].l,0,m-1);
            int r=binary(s[i].r,0,m-1)-1;
            printf("%d %d\n",l,r);
            updata(l,r,s[i].f,1);
            ans+=(s[i+1].h-s[i].h)*tree[1].len;

        }
        printf("Test case #%d\n",t++);
        printf("Total explored area: %.2lf\n\n",ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值