• poj3277


    题意:给定每个矩形的高度以及底边在数轴上的起点和终点。各矩形间可能有重叠。问它们覆盖的总面积是多少。

    分析:线段树的题,开始以为不能用线段树,因为如果在已经插入了许多又瘦又高的楼的情况下,插入一个又矮又宽的楼横跨他们的话,就会对中间相交部分进行许多次修改复杂度远大于O(logn)。后来看了答案才知道,可以先把楼房按照高度从小到大排序,这样就不会出现这样的情况了。后来wa的原因是建树的范围比实际范围大了1个单位。另外,跨度横坐标需要离散化。

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    #define MAX_INTERVAL 40005
    
    struct Building
    {
        int a, b, h;
    }building[MAX_INTERVAL];
    
    struct Node
    {
        int l, r;
        long long h;
        Node *pleft, *pright;
        long long value;
    }tree[MAX_INTERVAL *4];
    
    int n, discrete[MAX_INTERVAL *2], node_cnt, discrete_num;
    
    bool operator < (const Building &a, const Building &b)
    {
        return a.h < b.h;
    }
    
    bool ok(int index, int a)
    {
        return discrete[index] >= a;
    }
    
    int binary_search(int start, int end, int a)
    {
        int l = start;
        int r = end;
        while (l < r)
        {
            int mid = (l + r) / 2;
            if (ok(mid, a))
                r = mid;
            else
                l = mid + 1;
        }
        return l;
    }
    
    void input()
    {
        discrete_num =0;
        node_cnt =0;
        scanf("%d", &n);
        for (int i =0; i < n; i++)
        {
            scanf("%d%d%d", &building[i].a, &building[i].b, &building[i].h);
            discrete[discrete_num++] = building[i].a;
            discrete[discrete_num++] = building[i].b;
        }
    }
    
    void buildtree(Node *proot, int s, int e)
    {
        proot->l = s;
        proot->r = e;
        proot->h = 0;
        proot->value = 0;
        if (s == e)
        {
            proot->pleft = proot->pright = NULL;
            return;
        }
        node_cnt++;
        proot->pleft = tree + node_cnt;
        node_cnt++;
        proot->pright = tree + node_cnt;
        int mid = (s + e) / 2;
        buildtree(proot->pleft, s, mid);
        buildtree(proot->pright, mid + 1, e);
    }
    
    void add(Node *proot, int start, int end, long long h)
    {
        if (start > proot->r || end < proot->l)
            return;
        start = max(start, proot->l);
        end = min(end, proot->r);
        if (start == proot->l && end == proot->r)
        {
            proot->h = h;
            proot->value = h * (discrete[proot->r + 1] - discrete[proot->l]);
            return;
        }
        if (proot->h != -1 && proot->r != proot->l)
        {
            add(proot->pleft, proot->pleft->l, proot->pleft->r, proot->h);
            add(proot->pright, proot->pright->l, proot->pright->r, proot->h);
            proot->h = -1;
        }
        add(proot->pleft, start, end, h);
        add(proot->pright, start, end, h);
        proot->value = proot->pleft->value + proot->pright->value;
    }
    
    void discretization(int discrete[], int &discrete_num)
    {
        sort(discrete, discrete + discrete_num);
        discrete_num = unique(discrete, discrete + discrete_num) - discrete;
    }
    
    int main()
    {
        input();
        sort(building, building + n);
        discretization(discrete, discrete_num);
        buildtree(tree, 0, discrete_num - 2);
        for (int i =0; i < n; i++)
        {
            int l = binary_search(0, discrete_num - 1, building[i].a);
            int r = binary_search(0, discrete_num - 1, building[i].b);
            add(tree, l, r - 1, building[i].h);
        }
        printf("%lld\n", tree->value);
        return 0;
    }
    View Code
  • 相关阅读:
    Linux- 恢复.swp文件
    codeforces contest 1111
    bzoj2589【 Spoj 10707】 Count on a tree II
    20190129模拟题
    loj6070【山东集训第一轮Day4】基因
    bzoj4784【zjoi2017】仙人掌
    bzoj4520【cqoi2016】K远点对
    【学习笔记】BEST定理
    bzoj2441【中山市选】小W的问题
    bzoj3203【sdoi2013】保护出题人
  • 原文地址:https://www.cnblogs.com/rainydays/p/1965321.html
Copyright © 2020-2023  润新知