HDU 1255 覆盖的面积(线段树:扫描线求面积并)

时间:2023-03-09 09:55:35
HDU 1255 覆盖的面积(线段树:扫描线求面积并)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255

题目大意:给你若干个矩形,让你求这些矩形重叠两次及以上的部分的面积。

解题思路:模板题,跟HDU 1542  Atlantis一样是求面积并,唯一的差别是这题要求的是重叠两次以上的面积,只要将cnt>0的条件改为cnt>1即可。

代码:

 #include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<string>
#define LC(a) (a<<1)
#define RC(a) (a<<1|1)
#define MID(a,b) ((a+b)>>1)
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int N=2e3+; struct node{
double x1,x2,h,flag;
node(){}
node(double a,double b,double c,double d){
x1=a;x2=b;h=c;flag=d;
}
}a[N]; struct Node{
int l,r,cnt;
double sum;
}tree[*N]; double X[N]; bool cmp(node a,node b){
return a.h<b.h;
} int bin_search(double num,int l,int r){
while(l<=r){
int mid=(l+r)/;
if(X[mid]==num)
return mid;
else if(X[mid]<num)
l=mid+;
else
r=mid-;
}
} void pushup(int p){
tree[p].cnt=(tree[LC(p)].cnt==tree[RC(p)].cnt?tree[LC(p)].cnt:-);
tree[p].sum=tree[LC(p)].sum+tree[RC(p)].sum;
} void pushdown(int p){
tree[LC(p)].cnt=tree[RC(p)].cnt=tree[p].cnt;
//由cnt>0改为cnt>1
if(tree[p].cnt<=)
tree[LC(p)].sum=tree[RC(p)].sum=;
else{
tree[LC(p)].sum=X[tree[LC(p)].r+]-X[tree[LC(p)].l];
tree[RC(p)].sum=X[tree[RC(p)].r+]-X[tree[RC(p)].l];
}
} void build(int p,int l,int r){
tree[p].l=l;
tree[p].r=r;
tree[p].cnt=;
if(l==r){
tree[p].sum=;
return;
}
build(LC(p),l,MID(l,r));
build(RC(p),MID(l,r)+,r);
pushup(p);
} void update(int p,int l,int r,int cnt){
if(l>tree[p].r||r<tree[p].l)
return;
if(l<=tree[p].l&&r>=tree[p].r&&tree[p].cnt!=-){
tree[p].cnt+=cnt;
if(tree[p].cnt>=)
tree[p].sum=X[tree[p].r+]-X[tree[p].l];
else
tree[p].sum=;
return;
}
if(tree[p].cnt!=-)
pushdown(p);
update(LC(p),l,r,cnt);
update(RC(p),l,r,cnt);
pushup(p);
} int main(){
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
int m1=,m2=;
for(int i=;i<=n;i++){
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
X[++m1]=x1;
a[m1]=node(x1,x2,y1,);
X[++m1]=x2;
a[m1]=node(x1,x2,y2,-);
}
//横坐标离散化
sort(a+,a++m1,cmp);
sort(X+,X++m1);
for(int i=;i<=m1;i++){
if(X[i]!=X[i-])
X[++m2]=X[i];
}
build(,,m2-);
double ans=;
//依次读入扫描线求重叠两次及以上的面积并
for(int i=;i<=m1-;i++){
int l=bin_search(a[i].x1,,m2);
int r=bin_search(a[i].x2,,m2)-;
update(,l,r,a[i].flag);
ans+=tree[].sum*(a[i+].h-a[i].h);
}
printf("%.2lf\n",ans);
}
return ;
}