• 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;
    }
             
    



  • 相关阅读:
    on条件与where条件的区别
    Sqlserver中如何创建链接服务器
    SQL Server 2008 R2 主从数据库同步
    网站性能优化
    检索COM 类工厂中CLSID 为 {00024500-0000-0000-C000-000000000046}的组件时失败
    text输入框中按下enter键时阻止刷新页面
    关于以DataTable形式批量写入数据的案例
    关于Excel导入的HDR=YES; IMEX=1详解
    一条结合where、group、orderby的linq语法
    Linq使用Group By经验总结
  • 原文地址:https://www.cnblogs.com/csnd/p/12062821.html
Copyright © 2020-2023  润新知