转自这里
#include<cstdio> #include<algorithm> #include<cstring> #define LMT 202 #define left l,m,x<<1 #define right m+1,r,x<<1|1 using namespace std; //shit double int 搞错了 struct line { double h,l,r; int d; line(void){} line(double y,double x1,double x2,int dd):h(y),l(x1),r(x2),d(dd){} bool operator<(const line &y)const { return h<y.h; } }ln[LMT]; double sum[LMT<<2],X[LMT]; int cnt[LMT<<2]; void pushup(int l,int r,int x)//计算在这个纵坐标值的范围内,横轴的总长度 { if(cnt[x])sum[x]=X[r+1]-X[l];//这里可以防止漏选区域,看两个一大一小的矩阵合在一起的情况 else if(l==r)sum[x]=0; else sum[x]=sum[x<<1]+sum[x<<1|1]; /***** 这里道出了了用l,r-1的原因,如果是l,r,那么请计算一下只有一个矩阵的情况,这里 不会出现l==r的情况,会继续计算sum[x<<1],虽然一般来说值是对的,可是这是不符合程序 定义的,不严谨,而且很可能值也会错,对了,重叠情况也要考虑 *****/ } void update(int L,int R,int c,int l,int r,int x) { if(L<=l&&r<=R) { cnt[x]+=c; pushup(l,r,x); return; } int m=(l+r)>>1; if(L<=m)update(L,R,c,left); if(R>m)update(L,R,c,right); pushup(l,r,x); } int equry(double key,int n)//二分查找 { int m,l=0,r=n; while(l<=r) { m=(l+r)>>1; if(key==X[m])return m; if(key>X[m])l=m+1; else r=m-1; } return -1; } int main(void) { int n,k,I=1; double ans; while(~scanf("%d",&n)&&n>0) { double a,b,c,d; int num=0; ans=0; while(n--) { scanf("%lf%lf%lf%lf",&a,&b,&c,&d); ln[num]=line(b,a,c,1); X[num]=a; num++; ln[num]=line(d,a,c,-1); X[num]=c; num++; } sort(ln,ln+num); sort(X,X+num); memset(sum,0,sizeof(sum)); memset(cnt,0,sizeof(cnt)); k=1; for(int i=1;i<num;i++) if(X[i]!=X[i-1])X[k++]=X[i]; for(int i=0;i<num-1;i++) { int l=equry(ln[i].l,k-1),r=equry(ln[i].r,k-1)-1; if(l<=r)//原代码此处有事 { update(l,r,ln[i].d,0,k-1,1);//可能有重叠情况 ans+=sum[1]*(ln[i+1].h-ln[i].h); } } printf("Test case #%d\nTotal explored area: %.2lf\n\n",I++,ans); } return 0; }