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
原文地址:https://www.cnblogs.com/rainydays/p/1965321.html