poj 3277 - 线段树巩固

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




 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值