HDU 1542 Atlantics 线段树+离散化扫描

将 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 }

 

你可能感兴趣的:(ant)