扫描线

求矩形面积并

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const double eps = 1e-6;
const int N = 10000;

double ans, sum[N*4];
double X[N], x1[N], x2[N], yyy1[N], y2[N];
int flag[N], ti;

struct TR {
    double x1, x2, y;
    int opt;
    TR ( ) { }
    TR ( double x11, double x21, double yyy1, int opt1 ) 
        { x1 = x11, x2 = x21, y = yyy1, opt = opt1; }
} line[N*4];

bool cmp ( TR a, TR b ) { return a.y < b.y; }

int find ( double x, int n ) {
    int l = 1, r = n, mid;
    while ( l <= r ) {
        mid = (l+r) >> 1;
        if ( X[mid] == x ) return mid;
        else if ( X[mid] < x ) l = mid + 1;
        else r = mid - 1;
    }
}

void push_down ( int nd, int l, int r ) {
    if ( flag[nd] ) sum[nd] = X[r+1]-X[l];
    else if( l == r ) sum[nd] = 0;  
    else sum[nd] = sum[2*nd]+sum[2*nd+1]; 
}

void update ( int nd, int l, int r, int L, int R, int opt ) {
    if ( l >= L && r <= R ) {
        flag[nd] += opt; 
        push_down ( nd, l, r );
        return ;
    }
    int mid = (l+r) >> 1;
    if ( L <= mid ) update ( nd*2, l, mid, L, R, opt );
    if ( R > mid ) update ( nd*2+1, mid+1, r, L, R, opt );
    push_down ( nd, l, r );
}

int main ( ) {
    int n;
    while ( scanf ( "%d", &n ) == 1 ) {
        int num = 0;
        if ( n == 0 ) break;
        memset ( flag, 0, sizeof ( flag ) );
        memset ( sum, 0, sizeof ( sum ) );
        for ( int i = 1; i <= n; i ++ ) {
            scanf ( "%lf%lf%lf%lf", &x1[i], &yyy1[i], &x2[i], &y2[i] );
            line[++num] = TR ( x1[i], x2[i], yyy1[i], 1 );
            X[num] = x1[i];
            line[++num] = TR ( x1[i], x2[i], y2[i], -1 );
            X[num] = x2[i];
        }
        sort ( X+1, X+1+num );
        sort ( line+1, line+1+num, cmp );
        int k = 1;
        for ( int i = 2; i <= num; i ++ )
            if ( X[i] != X[i+1] ) X[++k] = X[i];//手动离散化
        double ans = 0;
        for ( int i = 1; i < num; i ++ ) {
            int L = find ( line[i].x1, k );//手动lower_bound
            int R = find ( line[i].x2, k ) - 1;//左闭右开
            update ( 1, 1, k, L, R, line[i].opt );
            ans += sum[1] * (line[i+1].y-line[i].y);
        }
        printf ( "Test case #%d\nTotal explored area: %.2lf\n\n", ++ti, ans );
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值