poj 1151 线段树+扫描线(Atlantis矩形面积)

题意:给定n个矩形 (n<= 100),其顶点坐标是浮点数,可能互相重叠,问这些矩形覆盖到的面积是多大。

思路:线段树+扫描线。用一条直线从左到右扫描,碰到一条矩形竖边的时候,就计算该直线有多长被矩形覆盖,以及被覆盖部分是覆盖了几重。碰到矩形左边,要增加被覆盖的长度,碰到右边, 要减少被覆盖的长度。每碰到一条矩形的纵边,覆盖面积就增加 Len * 该纵边到下一条纵边的距离。Len是此时扫描线被矩形覆盖的长度。

在Y轴进行离散化。n个矩形的2n个横边纵 坐标共构成最多2n-1个区间的边界,对这些区间编号,建立起线段树。

注意灵活运用stl提供的函数。

unique的作用是从输入序列中“删除”所有相邻的重复元素,即去重。

lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置,在本题中即返回查找到的y数组下标。

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define clc(s,t) memset(s,t,sizeof(s))
#define INF 0x3fffffff
#define N 100005
struct line{                //表示矩形的竖边
    double x,y1,y2;
    int l;                  //表示是否为矩形的左边
    bool operator<(const line &b) const{
        return x>1;
}
void build(int r,int left,int right){
    t[r].l = left;
    t[r].r = right;
    t[r].num = t[r].len = 0;
    if(left == right)
        return;
    build(r*2, left, mid(left, right));
    build(r*2+1, mid(left, right)+1, right);
}
void insert(int r,int left,int right){
    int mm = mid(t[r].l,t[r].r);
    if(t[r].l == left && t[r].r == right){
        t[r].len = y[right]-y[left-1];
        t[r].num++;
        return;
    }
    if(right<=mm)
        insert(r*2, left, right);
    else if(left>mm)
        insert(r*2+1, left, right);
    else{
        insert(r*2, left, mm);
        insert(r*2+1, mm+1, right);
    }
    if(t[r].num == 0)
        t[r].len = t[r*2].len + t[r*2+1].len;
}
void del(int r,int left,int right){
    int mm = mid(t[r].l, t[r].r);
    if(t[r].l == left && t[r].r == right){
        t[r].num--;
        if(t[r].num == 0){
            if(left == right)
                t[r].len = 0;
            else
                t[r].len = t[r*2].len+t[r*2+1].len;
        }
        return;
    }
    if(right <= mm)
        del(r*2,left,right);
    else if(left > mm)
        del(r*2+1,left,right);
    else{
        del(r*2,left,mm);
        del(r*2+1,mm+1,right);
    }
    if(t[r].num == 0)
        t[r].len = t[r*2].len+t[r*2+1].len;
}
int main(){
    while(scanf("%d",&n) && n){
        int i,j,y1,y2;
        double a,b,c,d,res=0;
        ylen = 0;
        for(i = 0;i


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