HDU 2795 Billboard

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2795

题意:

一块 高度为h, 宽度为 w 的公告牌, 铁公告,公告 的高度一样,都是1, 宽度不同, 给你n个公告,下面n个宽度,如果这个公告能贴上,就 输出 贴在第几行,不能贴上, 输出- 1 . 注意:每个贴公告的人都尽量不想把公告贴到高处. 公告不能贴在别的上面

思路:

看数据规模, 公告牌的高度h和宽度w 均为 10^9, 最多有 n 200000个公告. 

建树,  以每行为 叶子节点,建立 min(h,n) 个节点. 因为h > n有n个公告,最多占用n行,   父结点 记录 孩子节点的 最大剩余宽度, 更新即可

如果父结点记录 的是孩子节点 总共的 剩余量, 会TLE||~~||,想想为什么

代码:

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;

#define maxn  200005
struct Tree
{
	int left, rignt, num;
}node[maxn << 2];

int f;

void BuildTree(int i, int num, int l, int r);

void Update(int i, int num);

int main()
{
	int h, w, q;
	while(~scanf("%d %d %d", &h, &w, &q))
	{
		int n = h < q ? h :q;

		BuildTree(1, w, 1, n);
		while(q--)
		{
			int len;
			f = 0;
			scanf("%d", &len);
			Update(1, len);
			if(f) printf("%d\n", f);
			else printf("-1\n");
		}
	}
	return 0;
}

void BuildTree(int i, int num, int l, int r)
{
	node[i].left = l;
	node[i].rignt = r;
	node[i].num = num;
	if(l == r) return;
	int mid = (l + r) >> 1;
	BuildTree(i << 1, num, l, mid);
	BuildTree(i << 1 | 1, num, mid + 1, r);
}

void Update(int i, int num)
{
	//printf("i = %d\n", i);
	if(node[i].num < num) return;
	//if(f) return;
	if(node[i].left == node[i].rignt)
	{
		//printf("f = %d\n", f);
		f = node[i].left;
		node[i].num -= num;
		return;
	}
	Update(i << 1, num);
	if(!f) Update(i << 1 | 1, num);
	node[i].num = max(node[i << 1].num, node[i << 1 | 1].num);

}



posted @ 2015-02-09 22:04  豪气干云  阅读(158)  评论(0编辑  收藏  举报