zoukankan      html  css  js  c++  java
  • 离散化+线段树 POJ 3277 City Horizon

                                         POJ 3277 City Horizon

    Time Limit: 2000MS

     

    Memory Limit: 65536K

    Total Submissions: 18466

     

    Accepted: 5077

    Description

    Farmer John has taken his cows on a trip to the city! As the sun sets, the cows gaze at the city horizon and observe the beautiful silhouettes formed by the rectangular buildings.

    The entire horizon is represented by a number line with N (1 ≤ N ≤ 40,000) buildings. Building i's silhouette has a base that spans locations Ai through Bi along the horizon (1 ≤ Ai < Bi ≤ 1,000,000,000) and has height Hi (1 ≤ Hi ≤ 1,000,000,000). Determine the area, in square units, of the aggregate silhouette formed by all N buildings.

    Input

    Line 1: A single integer: N 
    Lines 2..N+1: Input line i+1 describes building i with three space-separated integers: AiBi, and Hi

    Output

    Line 1: The total area, in square units, of the silhouettes formed by all N buildings

    Sample Input

    4
    2 5 1
    9 10 4
    6 8 2
    4 6 3

    Sample Output

    16

    Hint

    The first building overlaps with the fourth building for an area of 1 square unit, so the total area is just 3*1 + 1*4 + 2*2 + 2*3 - 1 = 16.
     1 /*做法:因为所有矩形的都在一个X轴上,就把X方向是做线段树,每一个进行区间覆盖,最后查询到单点,计算总的面积,因为以X轴的坐标建立线段树,空间过大,可以离散化,用不超过40000个点表示坐标*/
     2 #include<iostream>
     3 using namespace std;
     4 #include<cstdio>
     5 #include<cstring>
     6 #include<algorithm>
     7 #define N 40010
     8 typedef long long ll;
     9 ll zl[N],yl[N],hig[N],seg[N<<1];
    10 int n,len,cnt=0;
    11 struct Tree{
    12     ll hi;
    13     int l,r;
    14 }tree[N<<3];
    15 void build_tree(int l,int r,int k)
    16 {
    17     tree[k].r=r;
    18     tree[k].l=l;
    19     tree[k].hi=0;
    20     if(l+1==r) return;
    21     int mid=(l+r)>>1;
    22     build_tree(l,mid,k<<1);
    23     build_tree(mid,r,k<<1|1);
    24 }
    25 void bing(int l,int r,ll z,ll y,int i,int k)
    26 {
    27     if(seg[l]>=z&&seg[r]<=y)
    28     {
    29         if(hig[i]>tree[k].hi)
    30           tree[k].hi=hig[i];
    31         return ;
    32     }
    33     int mid=(l+r)>>1;//进行区间覆盖的时候,要看清楚条件,去覆盖哪段区间 
    34     if(y<=seg[mid])
    35       bing(l,mid,z,y,i,k<<1);
    36     else if(z>=seg[mid])
    37       bing(mid,r,z,y,i,k<<1|1);
    38     else {
    39       bing(l,mid,z,y,i,k<<1);    
    40       bing(mid,r,z,y,i,k<<1|1);
    41     }
    42 }
    43 ll Solve(int h,int k,int l,int r)
    44 {
    45     if(tree[k].hi<h)
    46       tree[k].hi=h;/*相当于懒惰标记,是否父亲区间的h改变,但是孩子区间的高度没有变*/
    47     if(l+1==r)/*求面积并,必须查询到单点,因为小区间的高度>=大区间的高度*/
    48        return (ll)(seg[r]-seg[l])*tree[k].hi;/*因为最后是这种形式,所以必须是前闭后开区间,全闭区间是没法做的。*/ 
    49     int mid=(l+r)>>1;
    50     ll zzz=Solve(tree[k].hi,k<<1,l,mid);
    51     ll yyy=Solve(tree[k].hi,k<<1|1,mid,r);
    52     return zzz+yyy;
    53 }
    54 int main()
    55 {
    56     while(scanf("%d",&n)==1)
    57     {
    58       seg[0]=0;
    59       for(int i=1;i<=n;++i)
    60       {
    61         //cin>>zl[i]>>yl[i]>>hig[i];
    62         scanf("%d%d%d",&zl[i],&yl[i],&hig[i]);
    63         seg[++seg[0]]=zl[i];
    64         seg[++seg[0]]=yl[i];
    65       }
    66       sort(seg+1,seg+seg[0]+1);
    67       cnt=unique(seg+1,seg+seg[0]+1)-seg-1;/*去重,用最少的节点*/
    68       memset(tree,0,sizeof(0));
    69       build_tree(1,cnt,1);/*不是build_tree(1,cnt+1,1);因为这样会存在[cnt,cnt+1),这个区间是不存在的,因为没有cnt+1这个点,再去求面积的话,会出来负数*/
    70       for(int i=1;i<=n;++i)
    71         bing(1,cnt,zl[i],yl[i],i,1);
    72       cout<<Solve(0,1,1,cnt);
    73     }
    74     return 0;
    75  } 
  • 相关阅读:
    Spring Boot:自动配置原理
    centos7安装zookeeper
    spring集成RabbitMQ
    centos7安装RabbitMQ
    centos7安装MongoDB4.0(yum安装)
    nginx日志分割
    centos7 yum安装nginx
    centos7使用cronolog分割tomcat8.5的catalina.out日志
    ubuntu18安装微信
    idea打开dashboard
  • 原文地址:https://www.cnblogs.com/c1299401227/p/5755256.html
Copyright © 2011-2022 走看看