扫描线终于看懂了。。。咕咕了快三个月$qwq$
对于所有的横线按纵坐标排序,矩阵靠下的线权值设为$1$,靠上的线权值设为$-1$,然后执行线段树区间加减,每次的贡献就是有效宽度乘上两次计算时的纵坐标之差。
$cnt$数组记录每个位置被覆盖的次数,$sum$数组用来记区间总长度(即有效宽度),所以每一次把$sum[1]$乘上高就行了。
注意到每个$r$都减了$1$,原因是原先的坐标是点的坐标,而现在一个位置代表一个区间。
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<cctype> #include<cstdlib> #include<vector> #include<queue> #include<map> #include<set> #define ls (tr<<1) #define rs (tr<<1|1) #define ull unsigned long long #define ll long long #define R register int using namespace std; namespace Fread { static char B[1<<15],*S=B,*D=B; #define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++) inline int g() { R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix; do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix; } inline bool isempty(const char& ch) {return ch<=36||ch>=127;} inline void gs(char* s) {register char ch; while(isempty(ch=getchar())); do *s++=ch; while(!isempty(ch=getchar()));} }using Fread::g; using Fread::gs; const int N=220; struct ln { double l,r,x; int w; ln() {} ln(double Ll,double rr,double xx,int ww) {l=Ll,r=rr,x=xx,w=ww;} bool operator < (const ln& that) const {return x<that.x;} }L[N]; int n,t,tot; double d[N]; int cnt[N<<2]; double sum[N<<2]; inline void upd(int tr,int l,int r) { if(cnt[tr]) sum[tr]=d[r+1]-d[l]; else if(l==r) sum[tr]=0; else sum[tr]=sum[ls]+sum[rs]; } inline void change(int tr,int l,int r,int LL,int RR,int vl) { if(LL<=l&&r<=RR) {cnt[tr]+=vl; upd(tr,l,r); return ;} R md=l+r>>1; if(LL<=md) change(ls,l,md,LL,RR,vl); if(RR>md) change(rs,md+1,r,LL,RR,vl); upd(tr,l,r); } signed main() { #ifdef JACK freopen("NOIPAK++.in","r",stdin); #endif while(scanf("%d",&n),n!=0) { memset(cnt,0,sizeof(cnt)),memset(sum,0,sizeof(sum)); tot=0; for(R i=1;i<=n;++i) { register double l,p,r,b; scanf("%lf%lf%lf%lf",&l,&p,&r,&b); d[++tot]=l,L[tot]=ln(l,r,p,1); d[++tot]=r,L[tot]=ln(l,r,b,-1); } sort(d+1,d+tot+1),sort(L+1,L+tot+1); n=unique(d+1,d+tot+1)-d-1; register double ans=0; for(R i=1;i<=tot;++i) { R l=lower_bound(d+1,d+n+1,L[i].l)-d; R r=lower_bound(d+1,d+n+1,L[i].r)-d-1; change(1,1,n,l,r,L[i].w); ans+=sum[1]*(L[i+1].x-L[i].x); } printf("Test case #%d Total explored area: %.2lf ",++t,ans); } }
2019.06.13