POJ 1151 Atlantis 线段树+离散化+扫描线

时空隧道


题意:
给出n个矩形,求矩形的并面积…


分析:
貌似讲了很多边的题…我还是写了一个晚上…
把矩形分成两个区间,上面的区间+1,下面的区间-1…
然后就转化为了区间覆盖问题…


代码如下:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=100+5;
int n,cnt,cas,tot;
double mp[maxn*2],ans;
struct M{
    double x1,y1,x2,y2;
    friend bool operator < (M x,M y){
        if(x.y1==y.y1)
            return x.y2<y.y2;
        return x.y1<y.y1;
    }
}s[maxn],G[maxn*2];
struct Tree{
    int l,r,cover;
    double lenth,sum; 
}tree[100000*4+5];
inline void build(int l,int r,int tr){
//  cout<<l<<" "<<r<<endl;
    tree[tr].l=l,tree[tr].r=r,tree[tr].cover=0,tree[tr].lenth=mp[r]-mp[l],tree[tr].sum=0;
    if(l+1==r)
        return;
    int mid=(l+r)>>1;
    build(l,mid,tr<<1),build(mid,r,tr<<1|1);
}
inline void change(int l,int r,int tr,int val){
//  cout<<l<<" "<<r<<" "<<tree[tr].l<<" "<<tree[tr].r<<endl;
    if(tree[tr].l==l&&tree[tr].r==r){
        tree[tr].cover+=val;
        if(tree[tr].cover>0)
            tree[tr].sum=tree[tr].lenth;
        else if(tree[tr].lenth<=1)
            tree[tr].sum=0;
        else
            tree[tr].sum=tree[tr<<1].sum+tree[tr<<1|1].sum;
        return;
    }
    int mid=(tree[tr].l+tree[tr].r)>>1;
    if(r<=mid)
        change(l,r,tr<<1,val);
    else if(l>=mid) 
        change(l,r,tr<<1|1,val);
    else
        change(l,mid,tr<<1,val),change(mid,r,tr<<1|1,val);
    if(tree[tr].cover>0)
        tree[tr].sum=tree[tr].lenth;
    else if(tree[tr].lenth<=1)
        tree[tr].sum=0;
    else
        tree[tr].sum=tree[tr<<1].sum+tree[tr<<1|1].sum;
}
signed main(void){
    cas=0;
    while(scanf("%d",&n)&&n){
        ans=0,cnt=tot=0;
        for(int i=1;i<=n;i++)
            scanf("%lf%lf%lf%lf",&s[i].x1,&s[i].y1,&s[i].x2,&s[i].y2),
            mp[++cnt]=s[i].x1,mp[++cnt]=s[i].x2,
            G[++tot].y1=s[i].y1,G[tot].x1=s[i].x1,G[tot].x2=s[i].x2,G[tot].y2=1,
            G[++tot].y1=s[i].y2,G[tot].x1=s[i].x1,G[tot].x2=s[i].x2,G[tot].y2=-1;
        sort(G+1,G+tot+1);sort(mp+1,mp+cnt+1);
        int len=unique(mp+1,mp+cnt+1)-mp-1;build(1,len,1);
        for(int i=1;i<=tot;i++){
        //  cout<<"i: "<<i<<endl;
            int lala,lalala;
            lala=lower_bound(mp+1,mp+len+1,G[i].x1)-mp;
            lalala=lower_bound(mp+1,mp+len+1,G[i].x2)-mp;//cout<<lala<<" "<<lalala<<endl;
            ans+=(G[i].y1-G[i-1].y1)*tree[1].sum;//cout<<tree[1].sum<<"  ";
            change(lala,lalala,1,G[i].y2);//cout<<ans<<endl;
        }
        printf("Test case #%d\nTotal explored area: %.2f \n\n",++cas,ans);
    }
    return 0;
}

by >_< NeighThorn

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值