这道题目和原来求矩形覆盖的面积差不多,这个只是它的一个特殊情况,那就是矩形底边都在x轴上。
不多说了,每天多一点点的理解,每天深入一点点,最后你会很快滴将你的想法转化为代码,这也许就是所谓的码力吧,编码的能力。
//这道题目其实就是面积覆盖,可以用原来拿到题目的源码,稍微改一下就ok //但是还是想学习一下,自己写写代码,深入了解线段树,希望大家能看明白 //其实有时候动手画一棵树,然后模拟几个点,可以加深你对线段树的理解 #include <iostream> #include <cstdio> #include <algorithm> using namespace std; int A[40001],B[40001],H[40001],sLine[80004]; int N = 0,n; struct Tree { int l,r,h; }tree[300000]; //每次线段树的题目都是这样建树滴,所以这个过程相信你并不陌生 void build (int t, int l, int r) { tree[t].l = l; tree[t].r = r; if (l == r - 1) { return; } int mid = (l + r) >> 1; build(2 * t, l, mid); build(2 * t + 1, mid, r); } //同样每次都会有插入树的操作,更新一些信息,这个要具体问题具体分析 void insert(int t, int i, int l, int r) { if (sLine[tree[t].l] == l && sLine[tree[t].r] == r) { if (tree[t].h < H[i]) { tree[t].h = H[i]; } return; } int mid = sLine[(tree[t].l + tree[t].r) >> 1]; if (r <= mid) { insert(2 * t, i, l, r); } else if (l >= mid) { insert(2 * t + 1, i, l, r); } else { insert(2 * t, i, l, mid); insert(2 * t + 1, i, mid, r); } } //求面积,注意这里之所以要有一个高度的参数,是因为insert的时候,并没有将高度更新到叶子节点,所以,叶子节点的高度并不一定是最大的高度,所以要用父节点的高度来更新。 long long count(int t, int h) { if (h > tree[t].h) { tree[t].h = h; } if (tree[t].r - tree[t].l == 1) { return (long long)(sLine[tree[t].r] - sLine[tree[t].l]) * tree[t].h; } return count(2 * t, tree[t].h) + count(2 * t + 1, tree[t].h); } int main() { scanf("%d", &n); for (int i = 1; i <= n; ++ i) { scanf("%d %d %d", &A[i], &B[i], &H[i]); sLine[++ N] = A[i]; sLine[++ N] = B[i]; } sort(sLine + 1, sLine + N + 1); //去掉重复的扫描线 N = unique(sLine + 1, sLine + N + 1) - sLine - 1; build(1, 1, N); for (int i = 1; i <= n; ++ i) { insert(1, i, A[i], B[i]); } printf("%lld\n", count(1, 0)); return 0; }