总体来说也是个模板题,但是要开两个线段树来保存被覆盖一次,两次的面积
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #include<algorithm> #define maxn 10000 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct seg{ double l,r,h; int s; seg(){} seg(double l,double r,double h,int s):l(l),r(r),h(h),s(s){} bool operator<(const seg & a)const{ return h<a.h; } }segs[maxn]; double data[maxn]; int tot,m; double len1[maxn<<2],len2[maxn<<2];//区间被覆盖一次,被覆盖两次,len1[rt]+len2[rt]=data[r+1]-data[l] int cnt[maxn<<2]; inline void pushup(int rt,int l,int r){ if(cnt[rt]>=2){ len2[rt]=data[r+1]-data[l]; len1[rt]=0; } else if(cnt[rt]==1){ if(l==r) len2[rt]=0; else len2[rt]=len2[rt<<1]+len2[rt<<1|1]+len1[rt<<1]+len1[rt<<1|1]; len1[rt]=data[r+1]-data[l]-len2[rt]; } else { if(l==r) len1[rt]=len2[rt]=0; else { len1[rt]=len1[rt<<1]+len1[rt<<1|1]; len2[rt]=len2[rt<<1]+len2[rt<<1|1]; } } } void update(int L,int R,int c,int l,int r,int rt){ if(L<=l && R>=r){ cnt[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); } void init(){ tot=m=0; memset(data,0,sizeof data); memset(len1,0,sizeof len1); memset(cnt,0,sizeof cnt); memset(len2,0,sizeof len2); } int main(){ int T,n; cin >> T; while(T--){ init(); scanf("%d",&n); for(int i=1;i<=n;i++){ double a,b,c,d; scanf("%lf%lf%lf%lf",&a,&b,&c,&d); data[tot]=a; segs[tot++]=seg(a,c,b,1); data[tot]=c; segs[tot++]=seg(a,c,d,-1); } sort(segs,segs+tot); sort(data,data+tot); m=unique(data,data+tot)-data; double ans=0; for(int i=0;i<tot;i++){ int L=lower_bound(data,data+m,segs[i].l)-data; int R=lower_bound(data,data+m,segs[i].r)-data-1; update(L,R,segs[i].s,0,m,1); ans+=len2[1]*(segs[i+1].h-segs[i].h); } printf("%.2lf ",ans); } return 0; }