Atlantis(hdu1542)

题意:求n个矩阵的面积并。

/*
  线段树维护扫描线
  把每个矩形看成两条线段,从左到右添加线段,如果是矩形左边的线段,那就给线段所在的区间(y值)cover+1,反之则cover-1。
  并且如果这条线段添加之前它所在的区间的cover>0,则统计面积。
  另外如果求面积的交集,线段所在的区间的cover>1时统计面积。 
  
  PS:个人认为某位大神写的博客很好理解(这位大神还搞了一个线段树专辑?%%%):
     http://www.cnblogs.com/ka200812/archive/2011/11/13/2247064.html
     但是我觉得第一种算法每次都要找到叶子节点,貌似有点浪费时间,然而第二种又不会。。。 
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#define N 110
using namespace std;
double y[N*2];int n,cnt,Cas;
struct node{
    double x,y_down,y_up;int flag;
    bool operator < (const node &s1)const{
        return x<s1.x;
    }
};node e[N*2];
struct Node{
    double x,y_down,y_up;int cover;
    int flag;//是否为叶子节点 
};Node tree[1000*N];

void build(int k,int l,int r){
    tree[k].cover=0;
    tree[k].x=-1;//代表这个区间最近一次的横坐标 
    tree[k].y_down=y[l];
    tree[k].y_up=y[r];
    tree[k].flag=0;
    if(l+1==r){
        tree[k].flag=1;
        return;
    }
    int mid=l+r>>1;
    build(k*2,l,mid);
    build(k*2+1,mid,r);
}

double insert(int k,double x,double l,double r,int flag){
    if(r<=tree[k].y_down||l>=tree[k].y_up) return 0;
    if(tree[k].flag){
        if(tree[k].cover>0){
            double ans=(x-tree[k].x)*(tree[k].y_up-tree[k].y_down);
            tree[k].cover+=flag;
            tree[k].x=x;
            return ans;
        }
        else {
            tree[k].cover+=flag;
            tree[k].x=x;
            return 0;
        }
    }
    double ans=0;
    ans+=insert(k*2,x,l,r,flag);
    ans+=insert(k*2+1,x,l,r,flag);
    return ans;
}

int main(){
    while(scanf("%d",&n)){
        if(!n) break;
        cnt=0;
        for(int i=1;i<=n;i++){
            double x1,y1,x2,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            y[++cnt]=y1;
            e[cnt].x=x1;
            e[cnt].y_down=y1;
            e[cnt].y_up=y2;
            e[cnt].flag=1;
            y[++cnt]=y2;
            e[cnt].x=x2;
            e[cnt].y_down=y1;
            e[cnt].y_up=y2;
            e[cnt].flag=-1;
        }
        sort(y+1,y+cnt+1);//写成了sort(y,y+cnt+1),1WA 
        sort(e+1,e+cnt+1);
        build(1,1,cnt);
        double ans=0;
        for(int i=1;i<=cnt;i++){
            ans+=insert(1,e[i].x,e[i].y_down,e[i].y_up,e[i].flag);
        }
        printf("Test case #%d
Total explored area: %.2f

",++Cas,ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/harden/p/6280026.html