当前位置: 代码迷 >> 综合 >> HDU 1255 覆盖的面积 (矩形面积并变形)
  详细解决方案

HDU 1255 覆盖的面积 (矩形面积并变形)

热度:74   发布时间:2023-11-22 00:31:55.0

解题

求覆盖至少两次的面积。
用sum表示被覆盖至少一次的长度,用ss表示被覆盖至少两次的长度。这题与hdu1542的区别就在于更新ss。
首先像hdu1542那样去更新sum(因为需要用到sum去更新ss)。
根据该区间被完全覆盖的次数来更新ss:
如果add大于1,那么ss等于整个区间。
如果add等于1,那么ss等于左子树的sum值加右子树的sum值。(因为该区间被完全覆盖一次,左子树被覆盖一次累加该区间就至少两次,同理累加右子树)。
如果是叶子结点,ss等于0.

AC代码

//280ms 2.1MB
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define lson p<<1
#define rson p<<1|1
using namespace std;const int maxn=3e3+100;
struct node
{int l,r;//线段树所维护的区间int add;//add为1表示加一次覆盖,为-1表示减一次覆盖double sum,ss;//对应的被覆盖y一次的长度、两次的长度
}T[maxn<<2];
struct line///从下到上扫描
{double h,L,R;//高度和左右端点int mark;//标记为1表示下边,为-1表示上边bool operator<(const line &o)const{return h<o.h;}
}li[maxn];
double pos[maxn];
void up(int p)
{//更新被覆盖至少一次的长度if(T[p].add) T[p].sum=pos[T[p].r-1]-pos[T[p].l-1];else if(T[p].l==T[p].r) T[p].sum=0;else T[p].sum=T[lson].sum+T[rson].sum;//更新被覆盖至少两次的长度if(T[p].add>1) T[p].ss=pos[T[p].r-1]-pos[T[p].l-1];//长度是对应在pos数组中的值的差//不是线段树所维护的区间长度else if(T[p].l==T[p].r) T[p].ss=0;//不全部覆盖且是叶子结点,一定没有被覆盖的部分else if(T[p].add==1) T[p].ss=T[lson].sum+T[rson].sum;else if(T[p].add==0) T[p].ss=T[lson].ss+T[rson].ss;
}
void build(int p,int l,int r)
{T[p].add=0;T[p].sum=0;T[p].ss=0;T[p].l=l,T[p].r=r;if(l+1==r) return ;///注意叶子结点是一个长度为1的线段int mid=(l+r)>>1;build(lson,l,mid);build(rson,mid,r);///注意是mid,不是mid+1
}
void update(int p,int x,int y,int c)
{if(T[p].l==x && T[p].r==y){T[p].add+=c;up(p);return ;}int mid=(T[p].l+T[p].r)>>1;if(y<=mid) update(lson,x,y,c);else if(x>=mid) update(rson,x,y,c);///注意是>=mid,不是>midelse{update(lson,x,mid,c);update(rson,mid,y,c);///注意是mid,不是mid+1}up(p);
}int main()
{int n,kase=0;scanf("%d",&kase);while(kase--){scanf("%d",&n);int cnt=0,d=0;for(int i=0; i<n; i++){double x1,y1,x2,y2;scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);pos[d++]=x1;pos[d++]=x2;li[cnt].h=y1;li[cnt].L=x1;li[cnt].mark=1;li[cnt++].R=x2;li[cnt].h=y2;li[cnt].L=x1;li[cnt].mark=-1;li[cnt++].R=x2;}sort(li,li+cnt);sort(pos,pos+d);int m=unique(pos,pos+d)-pos;build(1,1,m);double ans=0;for(int i=0; i<cnt; i++){int l=lower_bound(pos,pos+m,li[i].L)-pos+1;int r=lower_bound(pos,pos+m,li[i].R)-pos+1;ans+=i==0?0:(li[i].h-li[i-1].h)*T[1].ss;update(1,l,r,li[i].mark);}printf("%.2lf\n",ans);}return 0;
}