hdu 1225 求覆盖至少两次的区域的面积并
记录三个域,每次更新相关信息之后传递上来。
sum【】:当前节点的总共合法区间(被覆盖至少两次)
cover【】:当前节点区间被覆盖次数
once【】:区间内被覆盖一次的总量
其他的独立思考应该能想出来
View Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 2222;
double sum[maxn<<2],once[maxn<<2],x[maxn];
int cover[maxn<<2];
struct seg{
double l,r,h;
int flag;
seg(){}
seg(double _l,double _r,double _h,int _flag):l(_l),r(_r),h(_h),flag(_flag){}
bool operator < (const seg &cmp) const {
return h<cmp.h;
}
}horizontal_seg[maxn];
void pushup(int rt,int l,int r){
if(cover[rt]==1){
sum[rt]=once[rt<<1]+once[rt<<1|1]+sum[rt<<1]+sum[rt<<1|1];
once[rt]=x[r+1]-x[l]-sum[rt];
return ;
}
if(cover[rt]==2){
sum[rt]=x[r+1]-x[l];
once[rt]=0;
return ;
}
if(cover[rt]==0){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
once[rt]=once[rt<<1]+once[rt<<1|1];
return ;
}
}
void update(int L,int R,int c,int l,int r,int rt){
if(L<=l&&r<=R){
cover[rt]+=c;
pushup(rt,l,r);
return ;
}
int m=(l+r)>>1;
if(L<=m) update(L,R,c,lson);
if(R>m) update(L,R,c,rson);
pushup(rt,l,r);
}
int main(){
int n,i,j,tot,t;
double x1,x2,y1,y2;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
tot=0;
for(i=1;i<=n;i++){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
x[tot]=x1;
horizontal_seg[tot++]=seg(x1,x2,y1,1);
x[tot]=x2;
horizontal_seg[tot++]=seg(x1,x2,y2,-1);
}
sort(x,x+tot);
sort(horizontal_seg,horizontal_seg+tot);
int nx=unique(x,x+tot)-x;
memset(cover,0,sizeof(cover));
memset(sum,0,sizeof(sum));
memset(once,0,sizeof(once));
double area=0;
for(i=0;i<tot-1;i++){
int left=lower_bound(x,x+nx,horizontal_seg[i].l)-x;
int right=lower_bound(x,x+nx,horizontal_seg[i].r)-x-1;
update(left,right,horizontal_seg[i].flag,0,nx-1,1);
area+=sum[1]*(horizontal_seg[i+1].h-horizontal_seg[i].h);
}
printf("%.2lf\n",area);
}
return 0;
}