hdu 1542 Atlantis

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1542

题目大意:线段树+扫描线+面积并

注释:1.偶是菜鸟狗,从大牛那里copy过来的代码模板。

         2.推荐线段树求面积并的地址:http://www.cnblogs.com/ka200812/archive/2011/11/13/2247064.html

  1 #include<iostream>
  2 #include<string>
  3 #include<algorithm>
  4 #include<cstdio>
  5 using namespace std;
  6 
  7 struct node
  8 {
  9     int l;
 10     int r;
 11     int cover;
 12     double len;
 13 };
 14 
 15 node tree[2000];
 16 double yy[250];
 17 int n,len;
 18 
 19 struct Line
 20 {
 21     double y_down;
 22     double y_up;
 23     double x;
 24     int cover;
 25 };
 26 
 27 Line line[250];
 28 
 29 int cmp(Line a,Line b)
 30 {
 31     return a.x<b.x;
 32 }
 33 
 34 int find(double x)
 35 {
 36     int l=0,r=len,mid;//左闭右闭区间的二分
 37     while(l<=r)
 38     {
 39         mid=(l+r)/2;
 40         if(yy[mid]==x)
 41             return mid;
 42         if(yy[mid]<x)
 43             l=mid+1;
 44         else
 45             r=mid-1;
 46     }
 47     return l;
 48 }
 49 
 50 void build(int i,int l,int r)
 51 {
 52     tree[i].l=l;
 53     tree[i].r=r;
 54     tree[i].cover=0;
 55     tree[i].len=0;
 56     if(l+1==r)
 57         return;
 58     int mid=(l+r)/2;
 59     build(2*i,l,mid);
 60     build(2*i+1,mid,r);
 61 }
 62 
 63 void fun(int i)
 64 {
 65     if(tree[i].cover)
 66         tree[i].len=yy[tree[i].r]-yy[tree[i].l]; //如果cover大于1,那么整段都可用于与下一线段求并面积
 67     else if(tree[i].l+1==tree[i].r) //叶子线段
 68         tree[i].len=0;
 69     else
 70         tree[i].len=tree[2*i].len+tree[2*i+1].len; //很简单的dp
 71 }
 72 
 73 void updata(int i,int l,int r,int cover)
 74 {
 75     if(tree[i].l>=r || tree[i].r<=l)
 76         return;
 77     if(tree[i].l>=l && tree[i].r<=r)
 78     {
 79         tree[i].cover+=cover;
 80         fun(i);
 81         return;
 82     }
 83     updata(2*i,l,r,cover);
 84     updata(2*i+1,l,r,cover);
 85     fun(i);
 86 }
 87 
 88 int main()
 89 {
 90     double x1,y1,x2,y2;
 91     int i,m,a,b,cas=1;
 92     //freopen("in.txt","r",stdin);
 93     while(scanf("%d",&n)==1 && n)
 94     {
 95         m=0;
 96         for(i=0;i<n;i++)
 97         {
 98             scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
 99             yy[m]=y1;
100             line[m].cover=1;
101             line[m].x=x1;
102             line[m].y_down=y1;
103             line[m++].y_up=y2;
104 
105             yy[m]=y2;
106             line[m].cover=-1;
107             line[m].x=x2;
108             line[m].y_down=y1;
109             line[m++].y_up=y2;
110         }
111         sort(yy,yy+m);
112         len=1;
113         for(i=1;i<m;i++)
114         {
115             if(yy[i-1]!=yy[i])
116                 yy[len++]=yy[i];//去除相同的点
117         }
118         len--;//新的yy数组下标还是从0开始的
119         build(1,0,len);
120         sort(line,line+m,cmp);
121         double ans=0;
122         printf("Test case #%d\n",cas++);
123         for(i=0;i<m-1;i++)
124         {
125             a=find(line[i].y_down);
126             b=find(line[i].y_up);
127             updata(1,a,b,line[i].cover);
128             ans+=tree[1].len*(line[i+1].x-line[i].x);  //tree[1].len已经保留了整个树与line[i+1]所能求并面积的长度
129         }
130         printf("Total explored area: %0.2lf\n\n",ans);
131     }
132     return 0;
133 }

 

posted @ 2014-03-20 18:35  huangxf  阅读(137)  评论(0编辑  收藏  举报