• [hdu1542] Atlantis (扫描线)


    题目传送门

    另一个传送到 codevs 3044 的传送门

    利用线段树维护一个扫描线。

    把每个水平线段都看作区间修改。

    从下到上依次扫描,是矩形下边界就添加,是矩形上边界就删除。

    线段树维护区间被覆盖了几层,以及区间内被覆盖了的部分的总长。

    每次添加线段时,用全部覆盖的长度乘以高度之差得到面积。

    挺好写的吧......

    卡了一上午,最后发现是离散化挂掉了。

    在Dr_J的指导下改成map离散化,就过了,呵呵呵。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<map>
      5 using namespace std;
      6 
      7 int n;
      8 int lb[805],rb[805],lv[805];
      9 double len[805],rx[405];
     10 
     11 struct pct{
     12     double l,r;
     13     double h;
     14     int ll,rr;
     15     int flag;
     16     void ins(double le,double re,double hx,int ll,int rr,int fl)
     17     {
     18         l=le;
     19         r=re;
     20         h=hx;
     21         ll=ll;
     22         rr=rr;
     23         flag=fl;
     24     }
     25 }pc[205];
     26 
     27 bool cmp(pct x,pct y)
     28 {
     29     return x.h<y.h;
     30 }
     31 
     32 bool dcp(double x,double y)
     33 {
     34     return x<y;
     35 }
     36 
     37 map<double,int>M;
     38 
     39 void build(int ord,int l,int r)
     40 {
     41     lb[ord]=l,rb[ord]=r;
     42     lv[ord]=0,len[ord]=0.00;
     43     if(l==r)return;
     44     int mid=(l+r)>>1;
     45     build(ord<<1,l,mid);
     46     build(ord<<1|1,mid+1,r);
     47 }
     48 
     49 void getlen(int ord)
     50 {
     51     if(lv[ord])len[ord]=rx[rb[ord]+1]-rx[lb[ord]];
     52     else if(lb[ord]==rb[ord])len[ord]=0;
     53     else len[ord]=len[ord<<1]+len[ord<<1|1];
     54 }
     55 
     56 void add(int ord,int l,int r,int v)
     57 {
     58     if(l<=lb[ord]&&r>=rb[ord])
     59     {
     60         lv[ord]+=v;
     61         getlen(ord);
     62         return;
     63     }
     64     int mid=(lb[ord]+rb[ord])>>1;
     65     if(l<=mid)add(ord<<1,l,r,v);
     66     if(r>mid)add(ord<<1|1,l,r,v);
     67     getlen(ord);
     68 }
     69 
     70 int main()
     71 {
     72     int cs=1;
     73     while(1)
     74     {
     75         scanf("%d",&n);
     76         if(!n)break;
     77         M.clear();
     78         int cnt=0;
     79         double ans=0.00;
     80         int rnt=0;
     81         int dnt=0;
     82         for(int i=1;i<=n;i++)
     83         {
     84             double le,re,hx,hy;
     85             scanf("%lf%lf%lf%lf",&le,&hx,&re,&hy);
     86             pc[++cnt].ins(le,re,hx,0,0,1);
     87             pc[++cnt].ins(le,re,hy,0,0,-1);
     88             rx[++rnt]=le;
     89             rx[++rnt]=re;
     90         }
     91         sort(rx+1,rx+rnt+1,dcp);
     92         for(int i=1;i<=rnt;i++)
     93         {
     94             if(M.find(rx[i])==M.end())
     95                 M[rx[i]]=++dnt;
     96             rx[dnt]=rx[i];
     97         }
     98         for(int i=1;i<=cnt;i++)
     99         {
    100             pc[i].ll=M[pc[i].l];
    101             pc[i].rr=M[pc[i].r];
    102         }
    103         sort(pc+1,pc+cnt+1,cmp);
    104         build(1,1,dnt);
    105         double btn=0.00;
    106         double lst=0.00;
    107         for(int i=1;i<=cnt;i++)
    108         {
    109             ans+=btn*(pc[i].h-lst);
    110             add(1,pc[i].ll,pc[i].rr-1,pc[i].flag);
    111             btn=len[1];
    112             lst=pc[i].h;
    113         }
    114         printf("Test case #%d
    ",cs);
    115         printf("Total explored area: %.2lf
    
    ",ans);
    116         cs++;
    117     }
    118     return 0;
    119 }
    hdu 1542 Atlantis
  • 相关阅读:
    上经 -- 乾【卦一】乾为天(三)
    上经 -- 乾【卦一】乾为天(一)
    8. Shell 文件包含
    7. Shell 函数
    6. Shell 流程控制
    5. test命令
    4. printf 命令
    3. Shell 基本运算符
    2. Shell 传递参数
    shell介绍
  • 原文地址:https://www.cnblogs.com/cervusy/p/9569650.html
Copyright © 2020-2023  润新知