个人博客→TanJX的自留地
覆盖的面积
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.
注意:本题的输入数据较多,推荐使用scanf读入数据.
Output
对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
Sample Input
2
5
1 1 4 2
1 3 3 7
2 1.5 5 4.5
3.5 1.25 7.5 4
6 3 10 7
3
0 0 1 1
1 0 2 1
2 0 3 1
Sample Output
7.63
0.00
题意
中文题
题解
扫描线,不再是用覆盖过一次的长度而是用覆盖两次的长度*两条扫描线之间的坐标差
代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <queue>
using namespace std;
#define me(x,y) memset(x,y,sizeof x)
#define lson rt<<1
#define rson rt<<1|1
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
typedef long long ll;
const int maxn = 2010;
const int INF = 0x3f3f3f3f;
const int MOD = 998244353;
#define eps 0.000000001
int n;
double Hash[maxn<<1];
struct Node{
double l,r,x;
int fg;
Node(){}
Node(double _l,double _r,double _x,double _fg) : l(_l),r(_r),x(_x),fg(_fg){}
bool operator < (const Node &a) const{
return x < a.x;
}
}node[maxn<<2];
struct N{
double len1,len2;
int col;
N(){}
N(double _len1,double _len2,int _col):len1(_len1),len2(_len2),col(_col){}
}nn[maxn<<2];
void build(int rt,int l,int r){
nn[rt] = N(0,0,0);
if(l == r){
return ;
}
int mid = (l + r) >> 1;
build(lson,l,mid);
build(rson,mid+1,r);
}
void Pushup(int rt,int l,int r){
if(nn[rt].col){
nn[rt].len1 = Hash[r+1] - Hash[l];
}
else if(l == r){
nn[rt].len1 = 0;
}
else{
nn[rt].len1 = nn[lson].len1 + nn[rson].len1;
}
if(nn[rt].col > 1){
nn[rt].len2 = Hash[r+1] - Hash[l];
}
else if(l == r){
nn[rt].len2 = 0;
}
else if(nn[rt].col == 1){
nn[rt].len2 = nn[lson].len1 + nn[rson].len1;
}
else{
nn[rt].len2 = nn[lson].len2 + nn[rson].len2;
}
}
void update(int rt,int L,int R,int l,int r,int val){
if(L <= l && R >= r){
nn[rt].col += val;
Pushup(rt,l,r);
return ;
}
int mid = (l + r) >> 1;
if(L <= mid){
update(lson,L,R,l,mid,val);
}
if(R > mid){
update(rson,L,R,mid+1,r,val);
}
Pushup(rt,l,r);
}
int main()
{
int t;
cin>>t;
while(t--){
scanf("%d",&n);
me(nn,0);
int m = 0;
double sum = 0;
for(int i = 1;i <= n; i++){
double x1,x2,y1,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
Hash[m] = y1;
node[m++] = Node(y1,y2,x1,1);
Hash[m] = y2;
node[m++] = Node(y1,y2,x2,-1);
}
int d = 1;
sort(Hash,Hash+m);
sort(node,node+m);
for(int i = 1; i < m; i++){
if(Hash[i-1] != Hash[i]){
Hash[d++] = Hash[i];
}
}
for(int i = 0; i < m; i++){
int l = lower_bound(Hash,Hash+d,node[i].l)-Hash;
int r = lower_bound(Hash,Hash+d,node[i].r)-Hash-1;
update(1,l,r,0,d-1,node[i].fg);
sum += nn[1].len2*(node[i+1].x - node[i].x);
}
printf("%.2lf\n",sum+eps);
}
return 0;
}