做法:注意更新,其实重叠就是有一个区域下方有2条以上没有被消除的线段。
#include<cstdio> #include<algorithm> #include<cstring> #define eps 1e8 #define left l,m,x<<1 #define right m+1,r,x<<1|1 const int LMT=4002; using namespace std; struct line { double x1,x2,y; int tag; bool operator<(const line &b)const { if(y!=b.y) return y<b.y; return tag>b.tag; } }e[LMT]; int cov[LMT<<2],cnt,n,ln; double ans,sum[LMT<<2],one[LMT<<2],myx[LMT]; void init(void) { memset(sum,0,sizeof(sum)); memset(cov,0,sizeof(cov)); memset(one,0,sizeof(one)); ln=cnt=ans=0; } void pushup(int x,int l,int r) { double len=myx[r+1]-myx[l]; if(cov[x]==2) { sum[x]=len; one[x]=0; } if(cov[x]==1) { if(l==r)sum[x]=0; else sum[x]=sum[x<<1]+sum[x<<1|1]+one[x<<1]+one[x<<1|1]; one[x]=len-sum[x]; } if(cov[x]==0) { if(l==r)sum[x]=one[x]=0; else { sum[x]=sum[x<<1]+sum[x<<1|1]; one[x]=one[x<<1]+one[x<<1|1]; } } } void update(int op,int L,int R,int l,int r,int x) { if(L<=l&&r<=R) { cov[x]+=op; pushup(x,l,r); return; } int m=(l+r)>>1; if(L<=m)update(op,L,R,left); if(R>m)update(op,L,R,right); pushup(x,l,r); } int myfind(double x) { int m,l=0,r=cnt-1; while(l<=r) { m=(l+r)>>1; if(myx[m]==x)return m; if(myx[m]<x)l=m+1; else r=m-1; } return -1; } int main(void) { int t,i,j,T,l,r; double x1,y1,x2,y2; scanf("%d",&T); while(T--) { init(); scanf("%d",&n); for(i=0;i<n;i++) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); e[ln].x1=x1;e[ln].x2=x2;e[ln].y=y1;e[ln].tag=1; ln++; e[ln].x1=x1;e[ln].x2=x2;e[ln].y=y2;e[ln].tag=-1; ln++; myx[cnt++]=x1;myx[cnt++]=x2; } sort(e,e+ln); sort(myx,myx+cnt); t=1; for(i=1;i<cnt;i++) if(myx[i]!=myx[i-1])myx[t++]=myx[i]; cnt=t; l=myfind(e[0].x1);r=myfind(e[0].x2); update(e[0].tag,l,r-1,0,cnt-1,1); for(i=1;i<ln;i++) { ans+=sum[1]*(e[i].y-e[i-1].y); l=myfind(e[i].x1);r=myfind(e[i].x2); update(e[i].tag,l,r-1,0,cnt-1,1); } printf("%.2lf\n",ans); } return 0; }