HDU 2796 线段树

线段树单点更新

题意:

一个广告板,知道它的长和宽,现在有N条信息需要在板上显示,每天信息都有自己的宽度,长度都为1。现在问你每条信息在哪个位置。

思路:

利用线段树,将有多少条信息或者高度作为线段树的最大区间,然后题目中说明要如果不能放在最上边(topmost),那么就放在最左边的上边(leftmost)。现在以样例为准来说明,依据样例数据,那么线段树的区间为1~3,那么首先宽度为2的进来,然后放在1的位置,宽度为4的进来放在2的位置(因为1位置所剩宽度不够)。。。第一个宽度为3的进来,发现1位置还剩下3的宽度刚好够,于是把这条信息放在这里面。。。最后一个宽度为3的进来发现有问题,这时候没有空间可以用来放置了,于是输出-1.

注意点:

输入输出都要用格式化输入输出,还有就是如果是长度大于信息条数,那么按照信息条数作为线段树最大区间,反之。

#include
#include
#include
using namespace std;
int H, W, N, T;
#define maxn 200100
#define Lchild rt<<1,L,m
#define Rchild rt<<1|1,m+1,R
int tree[maxn * 4];
void push_up(int rt)
{
	tree[rt] = tree[rt << 1] > tree[rt << 1 | 1] ? tree[rt << 1] : tree[rt << 1 | 1];
}
void build(int rt = 1, int L = 1, int R = T)
{
	if (L == R)
	{
		tree[rt] = W;
		return;
	}
	int m = (L + R) >> 1;
	build(Lchild);
	build(Rchild);
	push_up(rt);
}
int update(int w, int rt = 1, int L = 1, int R = T)
{
	if (tree[rt] < w)
		return -1;
	if (L == R&&tree[rt] >= w)
	{
		tree[rt] -= w;
		return L;
	}

	int m = (L + R) >> 1;
	int ret = -1;
	if (tree[rt << 1] >= w)
		ret = update(w, rt << 1, L, m);
	else if (tree[rt << 1 | 1] >= w)
		ret = update(w, rt << 1 | 1, m + 1, R);
	push_up(rt);
	return ret;
}
int main()
{
	while (~scanf_s("%d%d%d", &H, &W, &N))
	{
		T = N > H ? H : N;
		build();
		int n;
		for (int i = 1; i <= N; i++)
		{
			scanf_s("%d", &n);
			printf("%d\n", update(n));
		}
	}
	return 0;
}


你可能感兴趣的:(线段树)