将 x 轴上的点进行离散化,扫描线沿着 y 轴向上扫描
每次添加一条边不断找到当前状态有效边的长度 , 根据这个长度和下一条边形成的高度差得到一块合法的矩形的面积
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 6 using namespace std; 7 8 const int MAX=200+10; 9 int flag[MAX<<2];//记录某个区间的下底边个数 10 double sum[MAX<<2];//记录某个区间的下底边总长度 11 double x[MAX];//对x进行离散化,否则x为浮点数且很大无法进行线段树 12 13 struct Seg{//线段 14 double x1,x2,y; 15 int d; 16 Seg(){} 17 Seg(double x1 , double x2 , double y , int d):x1(x1),x2(x2),y(y),d(d){} 18 bool operator<(const Seg &a)const{ 19 return y<a.y; 20 } 21 }s[MAX]; 22 23 void updateCur(int n,int left,int right){ 24 if(flag[n]) sum[n] = x[right+1] - x[left];//表示该区间整个线段长度可以作为底边 25 else if(left == right) sum[n] = 0;//叶子结点则底边长度为0(区间内线段长度为0) 26 else sum[n] = sum[n<<1] + sum[n<<1|1]; 27 } 28 29 void update(int o , int l , int r , int s , int t , int d){ 30 if(s<=l && r<=t){//该区间是当前扫描线段的一部分,则该区间下底边总长以及上下底边个数差更新 31 flag[o] += d;//更新底边相差差个数 32 updateCur(o , l , r);//更新底边长 33 return; 34 } 35 int mid = (l + r)>>1 , ls = o<<1 , rs = o<<1|1; 36 if(mid >= s) update(ls , l , mid , s , t , d); 37 if(mid+1 <= t) update(rs , mid+1 , r , s , t , d); 38 updateCur(o , l , r); 39 } 40 41 int bin_search(double key , int n){ 42 int l = 0 , r = n-1; 43 while(l<=r){ 44 int mid = (l+r) >>1; 45 if(x[mid] == key) return mid; 46 if(x[mid] > key) r=mid-1; 47 else l=mid+1; 48 } 49 return -1; 50 } 51 52 int main() 53 { 54 // freopen("a.in" , "r" , stdin); 55 int n,cas=0; 56 double x1,x2,y1,y2; 57 while(scanf("%d" , &n) , n){ 58 int k=0; 59 for(int i=0;i<n;++i){ 60 cin>>x1>>y1>>x2>>y2; 61 x[k]=x1; 62 s[k++]=Seg(x1,x2,y1,1); 63 x[k]=x2; 64 s[k++]=Seg(x1,x2,y2,-1); 65 } 66 sort(x,x+k); 67 sort(s,s+k); 68 int t = unique(x , x+k) - x; 69 double ans=0; 70 71 for(int i=0;i<k;++i){//扫描线段 72 int pos1 = bin_search(s[i].x1 , t); 73 /* 74 这里因为是把它理解成合法线段,所以最右端第 i 个点 , 对应第 i - 1条边 75 同样道理,在updateCur中,计算有效线段长度时 , 需要x[r+1] 76 */ 77 int pos2 = bin_search(s[i].x2 , t)-1; 78 update(1 , 0 , t-1 , pos1 , pos2 , s[i].d);//扫描线段时更新底边长度和底边相差个数 79 ans += sum[1]*(s[i+1].y-s[i].y);//新增加面积 80 } 81 printf("Test case #%d\nTotal explored area: %.2lf\n\n",++cas,ans); 82 } 83 return 0; 84 }