Atlantis

poj1151:http://poj.org/problem?id=1151

题意:求矩形面积的并
题解:扫描线加线段树

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=202;//注意这里的初始化,不能开小了,是200条边 
 7 int num;//记录x坐标的个数 
 8 struct Node{
 9     double l;//边的左端点 
10     double r;//边的又端点 
11     int tp;//是出度边还是入度边 
12     double y;//边的纵坐标 
13  bool operator <(Node a) const{//按照纵坐标给边进行排序,一个比较器 
14             return y<a.y;
15       }
16 }line[2*maxn];
17 double arr[2*maxn];//用于离散化 
18 struct Edge{
19     int left;
20     int right;
21     int flag;//标记该点是加入还是删除 
22     double sum;
23 }node1[maxn*4];
24 void build(int l,int r,int idx){//建树 
25     node1[idx].left=l;
26     node1[idx].right=r;
27     if(l==r){
28         node1[idx].flag=0;
29         node1[idx].sum=0;
30         return;
31     }
32     int mid=(l+r)/2;
33     build(l,mid,idx<<1);
34     build(mid+1,r,idx<<1|1);
35     node1[idx].sum=node1[idx<<1].sum+node1[idx<<1|1].sum;
36 }
37 void update(int l,int r,int f,int idx){//更新 
38     if(node1[idx].left==node1[idx].right){
39           node1[idx].flag+=f;
40         if(node1[idx].flag)node1[idx].sum=arr[node1[idx].right+1]-arr[node1[idx].left];//注意这里的家一操作 
41         if(!node1[idx].flag)node1[idx].sum=0;
42         return ;
43     }
44     int mid=(node1[idx].left+node1[idx].right)/2;
45     if(mid>=r)update(l,r,f,idx<<1);
46     else if(mid<l)update(l,r,f,idx<<1|1);
47     else{
48         update(l,mid,f,idx<<1);
49         update(mid+1,r,f,idx<<1|1);
50     }
51     node1[idx].sum=node1[idx<<1].sum+node1[idx<<1|1].sum;//pushup上去 
52 }
53 int binaryserach(double x){//二分查找,也可以写成递归的形是     
54    int l,r,mid;
55       l=0,r=num+1;
56       while (r-l>1){
57             mid=(l+r)>>1;
58             if (arr[mid]<=x) l=mid;
59                else r=mid;
60       }
61       return l;
62 }
63 int main(){
64     int n;double x1,y1,x2,y2,ans;
65     int t=1;
66   while(~scanf("%d",&n)&&n){
67       num=0;
68       for(int i=1;i<=n;i++){
69           scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
70           line[2*i-1].l=x1;line[2*i-1].r=x2;line[2*i-1].y=y1;line[2*i-1].tp=1;
71           line[2*i].l=x1;line[2*i].r=x2;line[2*i].y=y2;line[2*i].tp=-1;
72           arr[++num]=x1;arr[++num]=x2;//离散化 
73       }
74       sort(arr+1,arr+num+1);//排序 
75       n*=2;ans=0;
76       sort(line+1,line+n+1);
77       build(1,n,1);
78      for(int i=1;i<=n;i++){
79           ans+=node1[1].sum*(line[i].y-line[i-1].y);
80           int l=binaryserach(line[i].l);
81           int r=binaryserach(line[i].r)-1;//注意这里是要得到区间,不是单个的点,所以要加1 
82            update(l,r,line[i].tp,1);
83       }
84       printf("Test case #%d\n",t++);
85     printf("Total explored area: %.2f\n\n",ans);  
86   }
87 }
View Code

 

转载于:https://www.cnblogs.com/chujian123/p/3426955.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值