HDOJ-1255 覆盖的面积(扫描线)

用len1[]表示相应区间覆盖了一次的长度,用len2[]表示相应区间覆盖了2次或2次以上的长度.cnt[]表示响应区间覆盖的次数.

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 1005

using namespace std;

struct Node{
    Node(){
    }
    Node(double a, double b, double c, int d){
        x1 = a;
        x2 = b;
        y = c;
        flag = d;
    }
    double x1, x2, y, flag;
    friend bool operator < (const Node &a, const Node&b){
        return a.y < b.y;
    }
}node[maxn<<1];
double len1[maxn<<3], len2[maxn<<3], p[maxn<<1];
int cnt[maxn<<3];
void Pushup(int n, int l, int r){

    if(cnt[n] >= 2){
        len2[n] = p[r+1] - p[l];
        len1[n] = 0;
    }
    else if(cnt[n] == 1){
        len1[n] = p[r+1] - p[l];
        if(l != r)
          len2[n] = len1[n<<1] + len1[n<<1|1] + len2[n<<1] + len2[n<<1|1];
        else 
          len2[n] = 0;
        len1[n] -= len2[n]; 
    }
    else {
        if(l == r){
            len1[n] = len2[n] = 0;
        }
        else {
            len1[n] = len1[n<<1] + len1[n<<1|1];
            len2[n] = len2[n<<1] + len2[n<<1|1];
        }
    }
}
void Update(int n, int l, int r, int L, int R, int s){

    if(l == L && R == r){
        cnt[n] += s;
        Pushup(n, l, r);
        return ;
    }
    int mid = (l + r) >> 1;
    if(R <= mid)
     Update(n<<1, l, mid, L, R, s);
    else if(L > mid)
     Update(n<<1|1, mid+1, r, L, R, s);
    else{
        Update(n<<1, l, mid, L, mid, s);
        Update(n<<1|1, mid+1, r, mid+1, R, s);
    }
    Pushup(n, l, r);
}
int main(){

    //freopen("in.txt", "r", stdin);
    int t;

    scanf("%d", &t);
    while(t--){

        memset(cnt, 0, sizeof(cnt));
        memset(len1, 0, sizeof(len1));
        memset(len2, 0, sizeof(len2));

        double a, b, c, d;
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++){
            scanf("%lf%lf%lf%lf", &a, &b, &c, &d);
            node[2*i-1] = Node(a, c, b, 1);
            node[2*i] = Node(a, c, d, -1);
            p[2*i-1] = a;
            p[2*i] = c;
        }
        sort(node+1, node+1+2*n);
        sort(p+1, p+1+2*n);
        int dd = unique(p+1, p+1+2*n) - p - 1;
        double sum = 0;
        for(int i = 1; i < 2*n; i++){

            int l = lower_bound(p+1, p+1+dd, node[i].x1) - p;
            int r = lower_bound(p+1, p+1+dd, node[i].x2) - p;
            if(l == r)
             continue;
            Update(1, 1, dd, l, r-1, node[i].flag); 
            sum += len2[1] * (node[i+1].y - node[i].y);
        }
        printf("%.2f\n", sum); 
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值