zoukankan      html  css  js  c++  java
  • 【BZOJ1645】[Usaco2007 Open]City Horizon 城市地平线 离散化+线段树

    【BZOJ1645】[Usaco2007 Open]City Horizon 城市地平线

    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 A_i through B_i along the horizon (1 <= A_i < B_i <= 1,000,000,000) and has height H_i (1 <= H_i <= 1,000,000,000). Determine the area, in square units, of the aggregate silhouette formed by all N buildings.

    N个矩形块,交求面积并.

    Input

    * Line 1: A single integer: N

    * Lines 2..N+1: Input line i+1 describes building i with three space-separated integers: A_i, B_i, and H_i

    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

    OUTPUT DETAILS:

    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.

    题解:一看就是离散化+线段树的题,可以先将h离散,再按a,b排序,用线段树维护扫描线来做,不过这样比较麻烦。

    因为本题中所有的矩形底边都在同一直线上,所以我们可以把这些矩形整体看成一棵线段树,线段树的区间就是每个a,b,线段树的权值就是h,然后按h排序,从小到大一个一个加到线段树里就行了。

    注意:a和b离散化后是2*40000的空间,所以线段树要开8*40000!2*4==8!!!

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define lson x<<1
    #define rson x<<1|1
    using namespace std;
    const int maxn=40010;
    typedef long long ll;
    struct edges
    {
        ll pos,org;
    }s[maxn<<1];
    struct house
    {
        ll sa,sb,sh;
    }p[maxn];
    int n,m;
    ll ts[maxn<<3],tag[maxn<<3],ref[maxn<<1];
    bool cmp1(edges a,edges b)
    {
        return a.pos<b.pos;
    }
    bool cmp2(house a,house b)
    {
        return a.sh<b.sh;
    }
    void pushdown(int l,int r,int x)
    {
        if(tag[x])
        {
            int mid=l+r>>1;
            ts[lson]=(ref[mid]-ref[l])*tag[x],ts[rson]=(ref[r]-ref[mid])*tag[x];
            tag[lson]=tag[rson]=tag[x];
            tag[x]=0;
        }
    }
    void pushup(int x)
    {
        ts[x]=ts[lson]+ts[rson];
    }
    void updata(int l,int r,int x,int a,int b,ll v)
    {
        if(a<=l&&r<=b)
        {
            ts[x]=(ref[r]-ref[l])*v;
            tag[x]=v;
            return ;
        }
        pushdown(l,r,x);
        int mid=l+r>>1;
        if(b<=mid)    updata(l,mid,lson,a,b,v);
        else if(a>=mid)    updata(mid,r,rson,a,b,v);
        else    updata(l,mid,lson,a,b,v),updata(mid,r,rson,a,b,v);
        pushup(x);
    }
    int main()
    {
        scanf("%d",&n);
        int i;
        for(i=1;i<=n;i++)
        {
            scanf("%lld%lld%lld",&p[i].sa,&p[i].sb,&p[i].sh);
            s[i*2-1].pos=p[i].sa,s[i*2].pos=p[i].sb;
            s[i*2-1].org=s[i*2].org=i;
        }
        sort(s+1,s+2*n+1,cmp1);
        for(i=1;i<=2*n;i++)
        {
            if(s[i].pos>ref[m])    ref[++m]=s[i].pos;
            if(s[i].pos==p[s[i].org].sa)    p[s[i].org].sa=m;
            else    p[s[i].org].sb=m;
        }
        sort(p+1,p+n+1,cmp2);
        for(i=1;i<=n;i++)
            updata(1,m,1,p[i].sa,p[i].sb,p[i].sh);
        printf("%lld",ts[1]);
        return 0;
    }
  • 相关阅读:
    不同数据类型在不同编译器下字节大小
    gbk/utf8/gb2312 编码中汉字字母数字所占字节数
    剑指Offer-12 矩阵中的路径
    螺旋矩阵(数组)问题(网易考点)
    C++ 多继承导致的指针偏移问题
    面试题--链表实现插入排序
    C++ 二叉树的深度优先遍历(前中后序)以及广度优先遍历
    (转)软连接和硬链接作用以及区别
    TCP/IP网络五层结构理解以及数据传输流程的理解图示
    常考知识点:进程与线程,多进程与多线程
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/6281746.html
Copyright © 2011-2022 走看看