zoukankan      html  css  js  c++  java
  • 线段树扫描线(一、Atlantis HDU

    扫描线求周长: hdu1828 Picture(线段树+扫描线+矩形周长)

    参考链接:https://blog.csdn.net/konghhhhh/java/article/details/78236036

    假想有一条扫描线,从左往右(从右往左),或者从下往上(从上往下)扫描过整个多边形(或者说畸形。。多个矩形叠加后的那个图形)。如果是竖直方向上扫描,则是离散化横坐标,如果是水平方向上扫描,则是离散化纵坐标。下面的分析都是离散化横坐标的,并且从下往上扫描的。

    扫描之前还需要做一个工作,就是保存好所有矩形的上下边,并且按照它们所处的高度进行排序,另外如果是上边我们给他一个值-1,下边给他一个值1,我们用一个结构体来保存所有的上下边

    struct segment 

    double l,r,h; //l,r表示这条上下边的左右坐标,h是这条边所处的高度 
    int f; //所赋的值,1或-1 
    }

    接着扫描线从下往上扫描,每遇到一条上下边就停下来,将这条线段投影到总区间上(总区间就是整个多边形横跨的长度),这个投影对应的其实是个插入和删除线段操作。还记得给他们赋的值1或-1吗,下边是1,扫描到下边的话相当于往总区间插入一条线段,上边-1,扫描到上边相当于在总区间删除一条线段(如果说插入删除比较抽象,那么就直白说,扫描到下边,投影到总区间,对应的那一段的值都要增1,扫描到上边对应的那一段的值都要减1,如果总区间某一段的值为0,说明其实没有线段覆盖到它,为正数则有,那会不会为负数呢?是不可能的,可以自己思考一下)。

    每扫描到一条上下边后并投影到总区间后,就判断总区间现在被覆盖的总长度,然后用下一条边的高度减去当前这条边的高度,乘上总区间被覆盖的长度,就能得到一块面积,并依此做下去,就能得到最后的面积

    (这个过程其实一点都不难,只是看文字较难体会,建议纸上画图,一画即可明白,下面献上一图希望有帮助) 

    例题:一、Atlantis HDU - 1542(覆盖面积)

    题意:

    给你一些矩形,让你求出来它们的总面积是多少(注意这些矩形可能会重叠)

    题解:

    就是上面讲的扫描线方法

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<iostream>
      4 #include<algorithm>
      5 using namespace std;
      6 #define lson i<<1,l,m
      7 #define rson i<<1|1,m+1,r
      8 const int maxn=205;
      9 double w[maxn<<1];
     10 struct trees
     11 {
     12     double l,r,h;
     13     int d;
     14     trees() {}
     15     trees(double a,double b,double c,int d): l(a),r(b),h(c),d(d) {}
     16     bool operator <(const trees q)const
     17     {
     18         return h<q.h;
     19     }
     20 } tree[maxn<<2];
     21 int cnt[maxn<<2];
     22 double sum[maxn<<2];
     23 void pushdown(int rt,int l,int r)
     24 {
     25     int m=(l+r)>>1;
     26     if(cnt[rt]!=-1)
     27     {
     28         cnt[rt<<1]=cnt[rt<<1|1]=cnt[rt];
     29         sum[rt<<1]=(cnt[rt] ? (w[m+1]-w[l]) : 0);
     30         sum[rt<<1|1]=(cnt[rt] ? (w[r+1]-w[m+1]) : 0);
     31     }
     32 }
     33 void pushup(int rt,int l,int r)
     34 {
     35     if(cnt[rt<<1] || cnt[rt<<1|1])
     36     {
     37         cnt[rt]=-1;
     38     }
     39     else if(cnt[rt<<1]!=cnt[rt<<1|1])
     40     {
     41         cnt[rt]=-1;
     42     }
     43     else cnt[rt]=cnt[rt<<1];
     44     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
     45 }
     46 void build(int rt,int l,int r)
     47 {
     48     if(l==r)
     49     {
     50         sum[rt]=0.0;
     51         cnt[rt]=0;
     52         return;
     53     }
     54     int m=(l+r)>>1;
     55     build(rt<<1,l,m);   //就是这里rt<<1的位置写错了,卧槽。。
     56     build(rt<<1|1,m+1,r);
     57     pushup(rt,l,r);
     58 }
     59 void update(int L,int R,int C,int rt,int l,int r)
     60 {
     61     if(l>=L && r<=R)
     62     {
     63         if(cnt[rt]!=-1)
     64         {
     65             cnt[rt]+=C;
     66             sum[rt]=(cnt[rt] ? (w[r+1]-w[l]) : 0);
     67             return;
     68         }
     69     }
     70     pushdown(rt,l,r);
     71     int m=(l+r)>>1;
     72     if(m>=L) update(L,R,C,rt<<1,l,m); 
     73     if(R>m) update(L,R,C,rt<<1|1,m+1,r);
     74     pushup(rt,l,r);
     75 }
     76 int searchs(int l,int r,double x)
     77 {
     78     int m=-1;
     79     while(l<=r)
     80     {
     81         m=(l+r)>>1;
     82         if(w[m]>x) r=m-1;
     83         else if(w[m]<x) l=m+1;
     84         else break;
     85     }
     86     return m;
     87 }
     88 //void PushDown(int i,int l,int r)
     89 //
     90 //{
     91 //
     92 //    int m=(l+r)/2;
     93 //
     94 //    if(cnt[i]!=-1)
     95 //
     96 //    {
     97 //
     98 //        cnt[i*2]=cnt[i*2+1]=cnt[i];
     99 //
    100 //        sum[i*2]= (cnt[i]?(w[m+1]-w[l]):0) ;
    101 //
    102 //        sum[i*2+1]= (cnt[i]?(w[r+1]-w[m+1]):0) ;
    103 //
    104 //    }
    105 //
    106 //}
    107 //
    108 //void PushUp(int i,int l,int r)
    109 //
    110 //{
    111 //
    112 //    if(cnt[i*2]==-1 || cnt[i*2+1]==-1)
    113 //
    114 //        cnt[i]=-1;
    115 //
    116 //    else if(cnt[i*2] != cnt[i*2+1])
    117 //
    118 //        cnt[i]=-1;
    119 //
    120 //    else
    121 //
    122 //        cnt[i]=cnt[i*2];
    123 //
    124 //    sum[i]=sum[i*2]+sum[i*2+1];
    125 //
    126 //}
    127 
    128 //void build(int i,int l,int r)
    129 //
    130 //{
    131 //
    132 //    if(l==r)
    133 //
    134 //    {
    135 //
    136 //        cnt[i]=0;
    137 //
    138 //        sum[i]=0.0;
    139 //
    140 //        return ;
    141 //
    142 //    }
    143 //
    144 //    int m=(l+r)/2;
    145 //
    146 //    build(lson);
    147 //
    148 //    build(rson);
    149 //
    150 //    PushUp(i,l,r);
    151 //
    152 //}
    153 //
    154 //void update(int ql,int qr,int v,int i,int l,int r)
    155 //
    156 //{
    157 //
    158 //    if(ql<=l && r<=qr)
    159 //
    160 //    {
    161 //
    162 //        if(cnt[i]!=-1)
    163 //
    164 //        {
    165 //
    166 //            cnt[i]+=v;
    167 //
    168 //            sum[i] = (cnt[i]? (w[r+1]-w[l]):0);
    169 //
    170 //            return ;
    171 //
    172 //        }
    173 //
    174 //    }
    175 //
    176 //    pushdown(i,l,r);
    177 //
    178 //    int m=(l+r)/2;
    179 //
    180 //    if(ql<=m) update(ql,qr,v,lson);
    181 //
    182 //    if(m<qr) update(ql,qr,v,rson);
    183 //
    184 //    pushup(i,l,r);
    185 //
    186 //}
    187 //
    188 //int searchs(double key,int n,double d[])
    189 //
    190 //{
    191 //
    192 //    int l=1,r=n;
    193 //
    194 //    while(r>=l)
    195 //
    196 //    {
    197 //
    198 //        int m=(r+l)/2;
    199 //
    200 //        if(d[m]==key)
    201 //
    202 //            return m;
    203 //
    204 //        else if(d[m]>key)
    205 //
    206 //            r=m-1;
    207 //
    208 //        else
    209 //
    210 //            l=m+1;
    211 //
    212 //    }
    213 //
    214 //    return -1;
    215 //
    216 //}
    217 int main()
    218 {
    219     int n,k=0;
    220     while(~scanf("%d",&n) && n)
    221     {
    222         int ans1=0,ans2=0;
    223         for(int i=1;i<=n;++i)
    224         {
    225             double x1,y1,x2,y2;
    226             scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
    227             w[++ans1]=x1;
    228             w[++ans1]=x2;
    229             tree[++ans2]=trees(x1,x2,y1,1);
    230             tree[++ans2]=trees(x1,x2,y2,-1);
    231         }
    232         sort(w+1,w+1+ans1);
    233         sort(tree+1,tree+1+ans2);
    234         int ans=1;
    235         for(int i=2;i<=ans1;++i)
    236         {
    237             if(w[i]!=w[i-1])
    238             {
    239                 w[++ans]=w[i];
    240             }
    241         }
    242         build(1,1,ans-1);
    243         double ret=0.0;
    244         for(int i=1;i<ans2;++i)
    245         {
    246             int l=searchs(1,ans,tree[i].l);
    247             int r=searchs(1,ans,tree[i].r)-1;
    248             //printf("%d %d %lf %lf
    ",l,r,tree[i].l,tree[i].r);
    249             if(l<=r) update(l,r,tree[i].d,1,1,ans-1);
    250             ret+=sum[1]*(tree[i+1].h-tree[i].h);
    251             //printf("%lf %lf %lf
    ",sum[1],tree[i+1].h,tree[i].h);
    252         }
    253         printf("Test case #%d
    Total explored area: %.2lf
    
    ",++k,ret);
    254     }
    255     return 0;
    256 }
    View Code

    例题: 二、覆盖的面积 HDU - 1255(重叠两次的面积)

    题意:

    给你一些矩形,让你求被覆盖至少两次区域的面积

    题解:

    和之前那个差不多,具体见代码

    代码:

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<iostream>
      4 #include<algorithm>
      5 using namespace std;
      6 #define lch(i) ((i)<<1)
      7 #define rch(i) ((i)<<1|1)
      8 const int maxn=2005;
      9 double w[maxn];
     10 struct shudui
     11 {
     12     double l,r,h;
     13     int d;
     14     shudui(){}
     15     shudui(double a,double b,double c,int d): l(a),r(b),h(c),d(d){}
     16     bool operator < (const shudui q)const
     17     {
     18         return h<q.h;
     19     }
     20 }v[maxn];
     21 struct trees
     22 {
     23     int l,r,m,cnt;
     24     double s,ss;
     25 }tree[maxn<<2];
     26 int n;
     27 void build(int l,int r,int rt)
     28 {
     29     tree[rt].l=l;
     30     tree[rt].r=r;
     31     int m=(l+r)>>1;
     32     tree[rt].m=m;
     33     tree[rt].s=tree[rt].ss=tree[rt].cnt=0;
     34     if(l==r)
     35     {
     36         return;
     37     }
     38     build(l,m,rt<<1);
     39     build(m+1,r,rt<<1|1);
     40 }
     41 void pushup(int rt)  //这种方法cnt是不会为负值的
     42 {
     43     if(tree[rt].cnt)
     44     {
     45         tree[rt].s=w[tree[rt].r+1]-w[tree[rt].l];
     46     }
     47     else if(tree[rt].l==tree[rt].r)
     48         tree[rt].s=0;
     49     else
     50         tree[rt].s=tree[rt<<1].s+tree[rt<<1|1].s;
     51     if(tree[rt].cnt>1)
     52         tree[rt].ss=w[tree[rt].r+1]-w[tree[rt].l];
     53     else if(tree[rt].l==tree[rt].r)
     54         tree[rt].ss=0;
     55     else if(tree[rt].cnt==1)
     56     {
     57         tree[rt].ss=tree[rt<<1].s+tree[rt<<1|1].s;
     58     }
     59     else tree[rt].ss=tree[rt<<1].ss+tree[rt<<1|1].ss;
     60 }
     61 void update(int L,int R,int C,int rt)
     62 {
     63     if(tree[rt].l==L && tree[rt].r==R)
     64     {
     65         tree[rt].cnt+=C; //这种方法cnt不往下传也不往上传
     66         pushup(rt);
     67         return;
     68     }
     69     int m=tree[rt].m;
     70     if(R<=m) update(L,R,C,rt<<1);
     71     else if(m<L) update(L,R,C,rt<<1|1);
     72     else
     73     {
     74         update(L,m,C,rt<<1);
     75         update(m+1,R,C,rt<<1|1);
     76     }
     77     pushup(rt);
     78 }
     79 //void cal(int rt)
     80 //{
     81 //    if(tree[rt].cnt)
     82 //        tree[rt].s = w[tree[rt].r+1] - w[tree[rt].l];
     83 //    else if(tree[rt].l == tree[rt].r)
     84 //        tree[rt].s=0;
     85 //    else
     86 //        tree[rt].s = tree[lch(rt)].s + tree[rch(rt)].s;
     87 ///**************************************************/
     88 //    if(tree[rt].cnt > 1)
     89 //        tree[rt].ss = w[tree[rt].r+1] - w[tree[rt].l];
     90 //    else if(tree[rt].l == tree[rt].r)
     91 //        tree[rt].ss = 0;
     92 //    else if(tree[rt].cnt == 1)
     93 //        tree[rt].ss = tree[lch(rt)].s + tree[rch(rt)].s;
     94 //    else
     95 //        tree[rt].ss = tree[lch(rt)].ss + tree[rch(rt)].ss;
     96 //}
     97 //
     98 //void update(int l , int r ,int v ,int rt)
     99 //{
    100 //    if(tree[rt].l==l && tree[rt].r==r)
    101 //    {
    102 //        tree[rt].cnt += v;
    103 //        cal(rt);
    104 //        return ;
    105 //    }
    106 //    int mid=tree[rt].m;
    107 //    if(r<=mid)     update(l,r,v,lch(rt));
    108 //    else if(l>mid) update(l,r,v,rch(rt));
    109 //    else
    110 //    {
    111 //        update(l,mid,v,lch(rt));
    112 //        update(mid+1,r,v,rch(rt));
    113 //    }
    114 //    cal(rt);
    115 //}
    116 int searchs(int l,int r,double x)
    117 {
    118     int  m;
    119     while(l<=r)
    120     {
    121         m=(l+r)>>1;
    122         if(w[m]>x) r=m-1;
    123         else if(w[m]<x) l=m+1;
    124         else break;
    125     }
    126     return m;
    127 }
    128 //int searchs(int low ,int high,double key)
    129 //{
    130 //    while(low <= high)
    131 //    {
    132 //        int mid=(low+high)>>1;
    133 //        if(w[mid] == key)
    134 //            return mid;
    135 //        else if(w[mid] < key)
    136 //            low=mid+1;
    137 //        else
    138 //            high=mid-1;
    139 //    }
    140 //    return -1;
    141 //}
    142 int main()
    143 {
    144     int t;
    145     scanf("%d",&t);
    146     while(t--)
    147     {
    148         scanf("%d",&n);
    149         int ans1=0,ans2=0;
    150         for(int i=1;i<=n;++i)
    151         {
    152             double x1,y1,x2,y2;
    153             scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
    154             w[++ans1]=x1;
    155             w[++ans1]=x2;
    156             v[++ans2]=shudui(x1,x2,y1,1);
    157             v[++ans2]=shudui(x1,x2,y2,-1);
    158         }
    159         sort(w+1,w+1+ans1);
    160         sort(v+1,v+1+ans2);
    161         int k=1;
    162         for(int i=2;i<=ans1;++i)
    163         {
    164             if(w[i]!=w[i-1])
    165             w[++k]=w[i];
    166         }
    167         build(1,k-1,1);
    168         double ret=0;
    169         for(int i=1;i<ans2;++i)
    170         {
    171             int l=searchs(1,k,v[i].l);
    172             int r=searchs(1,k,v[i].r)-1;  //不知道什么时候出现一个k-1
    173             if(l<=r)
    174             //printf("%d %d %lf %lf
    ",l,r,v[i].l,v[i].r);
    175             update(l,r,v[i].d,1);
    176             ret+=tree[1].ss*(v[i+1].h-v[i].h);
    177         }
    178         printf("%.2lf
    ",ret);
    179     }
    180     return 0;
    181 }
    182 //int main()
    183 //{
    184 //    int T;
    185 //    scanf("%d",&T);
    186 //    while(T--)
    187 //    {
    188 //        scanf("%d",&n);
    189 //        int i,k;
    190 //        for(i=0,k=0; i<n; i++,k+=2)
    191 //        {
    192 //            double x1,y1,x2,y2;
    193 //            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
    194 //            w[k]=x1; w[k+1]=x2;
    195 //            v[k].l=x1;   v[k].r=x2;   v[k].h=y1;   v[k].d=1;
    196 //            v[k+1].l=x1; v[k+1].r=x2; v[k+1].h=y2; v[k+1].d=-1;
    197 //        }
    198 //        sort(w,w+k);
    199 //        sort(v,v+k);
    200 //        int m=1;
    201 //        for(i=1; i<k; i++)
    202 //            if(w[i]!=w[i-1])
    203 //                w[m++]=w[i];
    204 //
    205 //        build(0,m-1,1);
    206 //        double res=0;
    207 //        for(i=0; i<k-1; i++)
    208 //        {
    209 //            int l=searchs(0,m-1,v[i].l);
    210 //            int r=searchs(0,m-1,v[i].r)-1;
    211 //            //printf("%d %d
    ",l,r);
    212 //            update(l,r,v[i].d,1);
    213 //            res += tree[1].ss*(v[i+1].h - v[i].h);
    214 //        }
    215 //        printf("%.2lf
    ",res);
    216 //    }
    217 //    return 0;
    218 //}
    View Code
  • 相关阅读:
    delphi实现FTP下载
    delphi中ClientDataSet的隐含功能
    删除注册的ODBC
    ZOJ 1041 Transmitters
    POJ 3232 Accelerator
    POJ 3460 Booksort
    UVa 11552 Fewest Flops
    SOJ 8064 Whack the Groundhog
    BNU OJ 29355 手速为王
    POJ 3322 Bloxorz I
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/12851117.html
Copyright © 2011-2022 走看看