zoukankan      html  css  js  c++  java
  • 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
    Total explored area: %.2lf
    
    ",++cas,ans);
    82     }
    83     return 0;
    84 }
  • 相关阅读:
    迷宫的最短路径(bfs)
    INNODB引擎概述
    mysql-innodb的事务日志
    python-set集合
    一个python代码练习
    关于arm 的字节对齐
    学习嵌入式为什么要有uboot(深度解析)
    uboot 添加 自定义命令
    关于UBOOT,LINUX内核编译,根文件系统的15个小问题
    s5p6818 Overview
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4190695.html
Copyright © 2011-2022 走看看