POJ 1151 Atlantis(线段树 - 离散化 扫描线 矩形面积并)

链接:http://poj.org/problem?id=1151
来源:POJ

  题意:给出每一个矩形的左上角和右下角,求出这一系列矩形的面积并

//沿垂直方向扫描
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<algorithm>
#define LNode x<<1
#define RNode x<<1|1
using namespace std;

typedef long long ll;
typedef pair<int,int>P;
const int Max_n=2e2+10;
const int inf=0x3f3f3f3f;
int tag[4*Max_n];
double xbin[Max_n],ybin[Max_n],Min[4*Max_n],cnt[Max_n*4];

struct rect{
    double x1,y1,x2,y2;
}r[Max_n];

struct event{
    int x1,x2,v;
    event(){};
    event(double x1,double x2,double v):x1(x1),x2(x2),v(v){};
};
vector<event>G[Max_n];

///区间最小值个数
void update(int x){//区间最小值的个数
    if(Min[LNode]==Min[RNode]){
        Min[x]=Min[LNode];
        cnt[x]=cnt[LNode]+cnt[RNode];
    }else if(Min[LNode]<Min[RNode]){
        Min[x]=Min[LNode];
        cnt[x]=cnt[LNode];
    }else{
        Min[x]=Min[RNode];
        cnt[x]=cnt[RNode];
    }
}

void down(int x){//标记下传函数(延迟修改技术)
    if(tag[x]!=0){//tag[x]!=0 区间加上某个数
        ///区间加上某个数
        tag[LNode]+=tag[x];
        tag[RNode]+=tag[x];
        ///区间最小值(区间最小值个数)
        Min[LNode]+=tag[x];
        Min[RNode]+=tag[x];
        tag[x]=0;
    }
}

//[A,B]:修改为v,[l,r]:当前结点对应的区间,x:当前结点
void change(int A,int B,int v,int l,int r,int x){///区间修改数据(log(n))
    if(A<=l&&B>=r) {
        ///区间加上某个数
        tag[x]+=v;
        Min[x]+=v;
        return ;
    }
    down(x);//修改之前,检查是否需要下传标记
    int mid=(l+r)>>1;
    if(A<=mid) change(A,B,v,l,mid,LNode);
    if(B>mid) change(A,B,v,mid+1,r,RNode);
    ///区间最小值个数
    update(x);
}

void build(int l,int r,int x){
    Min[x]=tag[x]=0;
    if(l==r){
        cnt[x]=xbin[l]-xbin[l-1];//离散化
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,LNode);
    build(mid+1,r,RNode);
    update(x);
}

int main(){
    int n,T=0;
    while(~scanf("%d",&n)&&n){
        for(int i=1;i<=n*4;i++){
            tag[i]=0;cnt[i]=0;
            Min[i]=0;
        }
        int xcnt=0,ycnt=0;
        for(int i=1;i<=n;i++){
            scanf("%lf%lf%lf%lf",&r[i].x1,&r[i].y1,&r[i].x2,&r[i].y2);
            xbin[++xcnt]=r[i].x1;xbin[++xcnt]=r[i].x2;
            ybin[++ycnt]=r[i].y1;ybin[++ycnt]=r[i].y2;
        }
        //离散化
        sort(xbin+1,xbin+xcnt+1);
        sort(ybin+1,ybin+ycnt+1);
        xcnt=unique(xbin+1,xbin+xcnt+1)-xbin-1;//去重
        ycnt=unique(ybin+1,ybin+ycnt+1)-ybin-1;
        for(int i=1;i<=n;i++){
            int x1=lower_bound(xbin+1,xbin+xcnt+1,r[i].x1)-xbin;
            int x2=lower_bound(xbin+1,xbin+xcnt+1,r[i].x2)-xbin;
            int y1=lower_bound(ybin+1,ybin+ycnt+1,r[i].y1)-ybin;
            int y2=lower_bound(ybin+1,ybin+ycnt+1,r[i].y2)-ybin;
            if(x1<x2){
                G[y1].push_back(event(x1+1,x2,1));
                G[y2].push_back(event(x1+1,x2,-1));
            }
        }
        xbin[0]=xbin[1];
        ybin[0]=ybin[1];
        build(1,xcnt,1);
        double ans=0;
        for(int i=1;i<=ycnt;i++){
            double tmp=cnt[1];
            if(Min[1]>0) tmp=0;
            ans+=(ybin[i]-ybin[i-1])*(xbin[xcnt]-xbin[1]-tmp);
            for(int j=0;j<(int)G[i].size();j++)
                change(G[i][j].x1,G[i][j].x2,G[i][j].v,1,xcnt,1);
        }
        for(int i=1;i<=ycnt;i++) G[i].clear();
        printf("Test case #%d\n",++T);
        printf("Total explored area: %.2f\n\n",ans);
    }
    return 0;
}
发布了166 篇原创文章 · 获赞 68 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_42217376/article/details/99680852
今日推荐