poj 3277 - 线段树巩固

来源:互联网 发布:ecplise不能运行java 编辑:程序博客网 时间:2024/05/19 07:28

这道题目和原来求矩形覆盖的面积差不多,这个只是它的一个特殊情况,那就是矩形底边都在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;}



 

原创粉丝点击