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; }