题目链接: 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);
}