zoukankan      html  css  js  c++  java
  • hdu1542 线段树扫描线求矩形面积的并

    题意:
          给你n个正方形,求出他们的所占面积有多大,重叠的部分只能算一次。
    思路:
          自己的第一道线段树扫描线题目,至于扫描线,最近会写一个总结,现在就不直接在这里写了,说下我的方法,我是离散化横坐标,然后去扫描纵坐标(反过来也行),把每一个长方形的两个宽边拿出来,按照高度排序,然后开始扫描,对于么一个区间的更新,我用的是暴力点更新,因为如果写段更新的话第二个权值没有想到什么好的一起更新的方法。

    然后在做另一道题目的时候发现这个方法超时了,没办法又去硬着头皮学了段更新的,段更新的扫描线应该大体有两种,我学了其中一个,然后又用段更新的做了下这个题目。


    一开始的暴力区间扫描

    
    

    #include<stdio.h>

    #include<string.h>
    #include<algorithm>
    
    #define lson l ,mid ,t << 1
    #define rson mid + 1 ,r ,t <<1 | 1
    
    using namespace std;
    
    typedef struct
    {
       double l ,r ,h;
       int mk;
    }EDGE;
    
    EDGE edge[100*2+10];
    double sum[100*2*4+10];
    double tmp[100*2+10];
    double num[100*2+10];
    int now[100*2+10];
    
    bool camp(EDGE a ,EDGE b)
    {
       return a.h < b.h;
    }
    
    void Pushup(int t)
    {
         sum[t] = sum[t<<1] + sum[t<<1|1];
    }
    
    void Update(int l ,int r ,int t ,int a ,int b)
    {
         if(l == r)
         {
            now[a] += b;
            if(now[a]) sum[t] = num[a+1] - num[a];
            else sum[t] = 0;
            return;
         }
         int mid = (l + r) >> 1;
         if(a <= mid) Update(lson ,a ,b);
         else Update(rson ,a ,b);
         Pushup(t);
    }
    
    int search_2(int n ,double now)
    {
        int low ,up ,mid ,ans;
        low = 0 ,up = n;
        while(low <= up)
        {
           mid = (low + up) >> 1;
           if(now <= num[mid])
           {
              ans = mid;
              up = mid -  1;
           }
           else low = mid + 1;
        }
        return ans;
    } 
       
    
    int main ()
    {
        int n ,i ,j ,cas = 1;
        double x1 ,x2 ,y1 ,y2;
        while(~scanf("%d" ,&n) && n)
        {
            int id = 0;
            for(i = 1 ;i <= n ;i ++)
            {
                scanf("%lf %lf %lf %lf" ,&x1 ,&y1 ,&x2 ,&y2);
                edge[++id].l = x1;
                edge[id].r = x2 ,edge[id].h = y1 ,edge[id].mk = 1;
                tmp[id] = x1;
                edge[++id].l = x1;
                edge[id].r = x2 ,edge[id].h = y2 ,edge[id].mk = -1;
                tmp[id] = x2;
            }
            sort(tmp + 1 ,tmp + id + 1);
            sort(edge + 1 ,edge + id + 1 ,camp);
            tmp[0] = -1;
            for(id = 0 ,i = 1 ;i <= n * 2 ;i ++)
            if(tmp[i] != tmp[i-1]) num[++id] = tmp[i];
            memset(now ,0 ,sizeof(now));
            memset(sum ,0 ,sizeof(sum));
            double ans = 0;
            edge[0].h = edge[1].h;
            for(i = 1 ;i <= n * 2 ;i ++)
            {
               ans += sum[1] * (edge[i].h - edge[i-1].h);
               int l = search_2(id ,edge[i].l);
               int r = search_2(id ,edge[i].r) - 1;
               for(j = l ;j <= r ;j ++)
               Update(1 ,id - 1 ,1 ,j ,edge[i].mk);
            }
            printf("Test case #%d
    " ,cas ++);
            printf("Total explored area: %.2lf
    
    " ,ans);
        }
        return 0;
    }
               
               
    
    后来的段更新扫描

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    
    #define lson l ,mid ,t << 1
    #define rson mid , r ,t << 1 | 1
    
    using namespace std;
    
    typedef struct
    {
       double l ,r ,h;
       int mk;
    }EDGE;
    
    EDGE edge[1000];
    
    double len[1000];
    double tmp[1000] ,num[1000];
    int cnt[1000];
    
    bool camp(EDGE a ,EDGE b)
    {
       return a.h < b.h;
    }
    
    void Pushup(int l ,int r ,int t)
    {
       if(cnt[t]) len[t] = num[r] - num[l];
       else if(l + 1 == r) len[t] = 0;
       else len[t] = len[t<<1] + len[t<<1|1];
    }
    void Update(int l ,int r ,int t ,int a ,int b ,int c)
    {
       if(l == a && r == b)
       {
          cnt[t] += c;
          Pushup(l ,r ,t);
          return;
       }
       int mid = (l + r) >> 1;
       if(b <= mid) Update(lson ,a ,b ,c);
       else if(a >= mid) Update(rson ,a ,b ,c);
       else 
       {
          Update(lson ,a ,mid ,c);
          Update(rson ,mid,b ,c);
       }
       Pushup(l ,r ,t);
    }
    
    int search_2(int id ,double now)
    {
       int low ,up ,mid ,ans;
       low = 1 ,up = id;
       while(low <= up)
       {
          mid = (low + up) >> 1;
          if(now <= num[mid])
          {
             ans = mid;
             up = mid - 1;
          }
          else low = mid + 1;
       }
       return ans;
    }
    
    int main ()
    {
       int id ,n ,i ,cas = 1;
       double x1 ,x2 ,y1 ,y2;
       while(~scanf("%d" ,&n) && n)
       {
          for(id = 0 ,i = 1 ;i <= n ;i ++)
          {
             scanf("%lf %lf %lf %lf" ,&x1 ,&y1 ,&x2 ,&y2);
             edge[++id].l = x1;
             edge[id].r = x2 ,edge[id].h = y1 ,edge[id].mk = 1;
             tmp[id] = x1;
             edge[++id].l = x1;
             edge[id].r = x2 ,edge[id].h = y2 ,edge[id].mk = -1;
             tmp[id] = x2;
          }
          sort(tmp + 1 ,tmp + id + 1);
          sort(edge + 1 ,edge + id + 1 ,camp);
          memset(len ,0 ,sizeof(len));
          memset(cnt ,0 ,sizeof(cnt));
          tmp[0] = -1;
          for(id = 0 ,i = 1 ;i <= n * 2 ;i ++)
          if(tmp[i] != tmp[i-1]) num[++id] = tmp[i];
          double ans = 0;
          edge[0].h = edge[1].h;
          for(i = 1 ;i <= n * 2 ;i ++)
          {
             ans += len[1] * (edge[i].h - edge[i-1].h);
             int l = search_2(id ,edge[i].l);
             int r = search_2(id ,edge[i].r);
             Update(1 ,id ,1 ,l ,r ,edge[i].mk);
          }
           printf("Test case #%d
    " ,cas ++);
           printf("Total explored area: %.2lf
    
    " ,ans);
        }
        return 0;
    }
             
    



  • 相关阅读:
    还记得那种 喜欢到不行的感觉么?
    从点到面,再从面到点
    草珊瑚的常见移动网站布局
    草珊瑚的CSS基础
    表驱动编程
    如果一切需要重学,2014年应该学哪些技术?
    揭开Makefile的神秘面纱
    VIM资源
    VIM跳转技巧
    前女友究竟是一种怎样的存在?
  • 原文地址:https://www.cnblogs.com/csnd/p/12062821.html
Copyright © 2011-2022 走看看