hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积

题目链接:点击打开链接

题目描写叙述:给定一些矩形,求这些矩形的总面积。假设有重叠。仅仅算一次

解题思路:扫描线+线段树+离散(代码从上往下扫描)

代码:

#include<cstdio>
#include <algorithm>
#define MAXN 110
#define LL ((rt<<1)+1)
#define RR ((rt<<1)+2)
using namespace std;
int n;
struct segment{
    double l,r,h;
    int f;
    bool operator<(const segment& b)const{
        return h>b.h;
    }
}sg[2*MAXN];
double pos[2*MAXN];
int id;
void addSegment(double x1,double y1,double x2,double y2){
    sg[id].l=x1;sg[id].r=x2;
    sg[id].h=y1;sg[id].f=1;
    pos[id++]=x1;
    sg[id].l=x1;sg[id].r=x2;
    sg[id].h=y2;sg[id].f=-1;
    pos[id++]=x2;
}
int binary(double key,int low,int high){
    while(low<=high){
        int mid=(low+high)/2;
        if(pos[mid]==key)
            return mid;
        else if(key<pos[mid])
            high=mid-1;
        else
            low=mid+1;
    }
    return -1;
}
struct Tree{
    int l,r;
    int cover;
    double len;
}tree[8*MAXN];
void build(int rt,int l,int r){
    tree[rt].l=l;
    tree[rt].r=r;
    tree[rt].cover=0;
    tree[rt].len=0;
    if(l==r-1)
        return;
    int mid=(l+r)>>1;
    build(LL,l,mid);
    build(RR,mid,r);
}
void pushup(int rt){
    if(tree[rt].cover)
        tree[rt].len=pos[tree[rt].r]-pos[tree[rt].l];
    else if(tree[rt].l==tree[rt].r-1)
        tree[rt].len=0;
    else
        tree[rt].len=tree[LL].len+tree[RR].len;
}
void update(int rt,int l,int r,int f){
    if(tree[rt].l==l&&tree[rt].r==r){
        tree[rt].cover+=f;
        pushup(rt);
        return;
    }
    int mid=(tree[rt].l+tree[rt].r)>>1;
    if(r<=mid)
        update(LL,l,r,f);
    else if(l>=mid)
        update(RR,l,r,f);
    else{
        update(LL,l,mid,f);
        update(RR,mid,r,f);
    }
    pushup(rt);
}
int main(){
    int Case=0;
    while(scanf("%d",&n)!=EOF&&n!=0){
        id=0;
        double x1,y1,x2,y2;
        for(int i=0;i<n;++i){
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            addSegment(x1,y1,x2,y2);
        }
        n=(n<<1);
        sort(sg,sg+n);
        sort(pos,pos+n);
        int m=1;
        for(int i=1;i<n;++i)
            if(pos[i]!=pos[i-1])
                pos[m++]=pos[i];
        build(0,0,m-1);
        double ans=0;
        int l=binary(sg[0].l,0,m-1);
        int r=binary(sg[0].r,0,m-1);
        update(0,l,r,sg[0].f);
        for(int i=1;i<n;i++){
            ans+=(sg[i-1].h-sg[i].h)*tree[0].len;
            l=binary(sg[i].l,0,m-1);
            r=binary(sg[i].r,0,m-1);
            update(0,l,r,sg[i].f);
        }
        printf("Test case #%d\n",++Case);
        printf("Total explored area: %.2f\n\n",ans);
    }
    return 0;
}
时间: 2024-12-29 11:51:35

hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积的相关文章

HDU1542_Atlantis(扫描线/线段树+离散)

解题报告 题目传送门 题意: 求矩形并面积. 思路: 离散+线段树+扫描线. #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; struct Seg { int v; double h,lx,rx; friend bool operator < (Seg a,Seg b) { return a.h<b

POJ训练计划1177_Picture(扫描线/线段树+离散)

解题报告 题意: 求矩形周长和. 思路: 左扫上扫,扫过了. #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; struct Seg { int lx,rx,ly,ry,h,v; friend bool operator < (Seg a,Seg b) { re

HDU1255_覆盖的面积(扫描线/线段树+离散)

解题报告 题目传送门 题意: 求面积交. 思路: 不会呀. 只知道线段树应该维护覆盖数大于2的线段长度. 不会更新,看了别人写的理解的,太菜了. 用sum1和sum2分别来表示覆盖数为1的区间长度和覆盖数为2的区间长度. 更新时即要更新sum1也要更新sum2: 区间如果被覆盖 sum1为实际区间长度,如果覆盖一次,sum2为左右子树的sum1和,覆盖两次就为实际区间长度. 没有被覆盖就直接等于左右子树的和. #include <algorithm> #include <iostream

ZOJ1659_Mobile Phone Coverage(扫描线/线段树+离散)

解题报告 题目传送门 题意: 求矩形面积并 思路: 扫描线+线段树.要离散化,坐标是浮点型的. 对于线段树(区间)与点坐标对应起来可以这样 区间[1,4]对应的线段树. #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; struct Seg { int v; double lx,rx,h; friend bool

POJ 1151 Atlantis 扫描线+线段树

点击打开链接 Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17252   Accepted: 6567 Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of pa

HDU 1542 Atlantis (线段树求矩阵覆盖面积)

题意:给你n个矩阵求覆盖面积. 思路:看了别人的结题报告 给定一个矩形的左下角坐标和右上角坐标分别为:(x1,y1).(x2,y2),对这样的一个矩形,我们构造两条线段,一条定位在x1,它在y坐标的区间是[y1,y2],并且给定一个cover域值为1:另一条线段定位在x2,区间一样是[y1,y2],给定它一个cover值为-1.根据这样的方法对每个矩形都构造两个线段,最后将所有的线段根据所定位的x从左到右进行排序 #include <iostream> #include <stdio.h

hdu1542 Atlantis (线段树+扫描线+离散化)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 9032    Accepted Submission(s): 3873 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i

hdu-1542 Atlantis(离散化+线段树+扫描线算法)

题目链接: Atlantis Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/32768 K (Java/Others) Problem Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include ma

poj1151 Atlantis——扫描线+线段树

题目:http://poj.org/problem?id=1151 经典的扫描线问题: 可以用线段树的每个点代表横向被矩形上下边分割开的每一格,这样将一个矩形的出现或消失化为线段树上的单点修改: 每个格子记录两个值:c(矩形存在情况),sum(对当前答案作出贡献的长度): 将y离散化作为建树的依据: 一开始没想到线段树上的点应该是横向的格子,写了个乱七八糟: #include<iostream> #include<cstdio> #include<cstring> #i