线段树 + 扫描线 - HDU 1255 - 覆盖的面积
对于每个区间结点,建立两个变量len1
,len2
len1
表示区间内被覆盖过一次且仅以次的线段长度len2
表示区间内被覆盖过大于等于两次的线段长度
因此,对于叶子结点:
if(l+1==r){
if(cover[rt]==1){
tree[rt].len1 = ordy[r]-ordy[l];
tree[rt].len2 = 0;
}else if(cover[rt] >= 2){
tree[rt].len1 = 0;
tree[rt].len2 = ordy[r] - ordy[l];
}else{
tree[rt].len1 = tree[rt].len2 = 0;
}
return;
}
对于非叶子节点
if(cover[rt] >= 2){
tree[rt].len1 = 0;
tree[rt].len2 = ordy[r] - ordy[l];
}else if(cover[rt] == 1){
tree[rt].len2 = tree[rt<<1].len1 + tree[rt<<1|1].len1 + tree[rt<<1].len2 + tree[rt<<1|1].len2;
tree[rt].len1 = ordy[r]-ordy[l]-tree[rt].len2;
}else{
tree[rt].len1 = tree[rt<<1].len1 + tree[rt<<1|1].len1;
tree[rt].len2 = tree[rt<<1].len2 + tree[rt<<1|1].len2;
}
完整代码
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define EPS 1e-9
const int N = 1000+50;
bool equals(double a,double b){
return fabs(a-b) < EPS;
}
struct node{
double len1; // 当前区间仅被覆盖过一次
double len2; // 当前区间至少被覆盖过两次的长度
node(){len1=0;len2=0;}
};
struct SL{
double x,upy,downy;
int d;
SL(){}
SL(double a,double b,double c,int d)
:x(a),upy(b),downy(c),d(d){}
bool operator<(SL&m){
if(!equals(x,m.x))
return x < m.x;
else return d > m.d;
}
};
int my_unique(double arr[],int arrlen){
arr[0]=arr[1]-1;
int ptr = 0;
for(int i = 1; i <= arrlen; i++){
if(equals(arr[i],arr[i-1])){
continue;
}else{
arr[++ptr] = arr[i];
}
}
return ptr;
}
int my_lower_bound(double arr[],int len,double val){ // 找到第一个大于等于val的值 ,如果大于等于val,r=mid
int l = 1,r = len;
while(l < r){
int mid = l+r>>1;
if(equals(arr[mid],val) || arr[mid] >= val){
r = mid;
}else{
l = mid+1;
}
}
return l;
}
int cnt;
int len;
SL SLarr[N<<1];
double ordy[N<<1];
int cover[N<<3];
node tree[N<<3];
void push_up(int l,int r,int rt){
if(l+1==r){
if(cover[rt]==1){
tree[rt].len1 = ordy[r]-ordy[l];
tree[rt].len2 = 0;
}else if(cover[rt] >= 2){
tree[rt].len1 = 0;
tree[rt].len2 = ordy[r] - ordy[l];
}else{
tree[rt].len1 = tree[rt].len2 = 0;
}
return;
}
if(cover[rt] >= 2){
tree[rt].len1 = 0;
tree[rt].len2 = ordy[r] - ordy[l];
}else if(cover[rt] == 1){
tree[rt].len2 = tree[rt<<1].len1 + tree[rt<<1|1].len1 + tree[rt<<1].len2 + tree[rt<<1|1].len2;
tree[rt].len1 = ordy[r]-ordy[l]-tree[rt].len2;
}else{
tree[rt].len1 = tree[rt<<1].len1 + tree[rt<<1|1].len1;
tree[rt].len2 = tree[rt<<1].len2 + tree[rt<<1|1].len2;
}
}
void update(int l,int r,int rt,int ul,int ur,int d){
if(ul <= l && ur >= r){
cover[rt] += d;
push_up(l,r,rt);
}else{
if(l+1==r)return;
int mid = l+r>>1;
if(ul <= mid){
update(l,mid,rt<<1,ul,ur,d);
}
if(ur > mid){
update(mid,r,rt<<1|1,ul,ur,d);
}
push_up(l,r,rt);
}
}
void clear(int l,int r,int rt){
tree[rt].len1 = tree[rt].len2 = 0;
cover[rt] = 0;
if(l+1==r)return;
int mid = l+r>>1;
clear(l,mid,rt<<1);
clear(mid,r,rt<<1|1);
}
int main(){
int T;
scanf("%d",&T);
for(int t = 1; t <= T; t++){
int n;
double xa,ya,xb,yb;
scanf("%d",&n);
cnt=len=0;
for(int i = 1;i <= n; i++){
scanf("%lf%lf%lf%lf",&xa,&ya,&xb,&yb);
SLarr[++cnt] = SL(xa,yb,ya,1);
ordy[cnt] = ya;
SLarr[++cnt] = SL(xb,yb,ya,-1);
ordy[cnt] = yb;
}
sort(ordy+1,ordy+1+cnt);
sort(SLarr+1,SLarr+1+cnt);
len = my_unique(ordy,cnt);
clear(1,len,1);
double ans = 0.00;
for(int i = 1; i <= cnt; i++){
ans += tree[1].len2 * (SLarr[i].x-SLarr[i-1].x);
int ul = my_lower_bound(ordy,len,SLarr[i].downy);
int ur = my_lower_bound(ordy,len,SLarr[i].upy);
update(1,len,1,ul,ur,SLarr[i].d);
}
printf("%.2f
",ans);
}
system("pause");
return 0;
}