Billboard 线段树

本文介绍了一种使用线段树解决公告板问题的方法。通过构建线段树并更新节点值来模拟公告的张贴过程,确保每次都能找到合适的张贴位置。文章提供了完整的代码实现,并解释了如何高效查询和更新黑板的剩余宽度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

每次贴公告时都尽可能上
线段树中的val表示在[l,r]范围内黑板所剩的最大宽度
每次查询都先往左查询,这样就可以优先贴在靠上的地方



#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int MAXN = 200005;
struct Node {
	int l, r;
	long long val;
	int mid() { return (l + r) >> 1; }
}Tree[MAXN * 4];

int idx[MAXN];

void buildTree(int rt, int l, int r, long long w)
{
	Tree[rt].l = l;
	Tree[rt].r = r;
	Tree[rt].val = w;
	if (l == r)
	{
		idx[l] = rt;
		return;
	}
	int m = Tree[rt].mid();
	buildTree(rt << 1, l, m, w);
	buildTree(rt << 1 | 1, m + 1, r, w);
}

void updata(int rt)
{
	if (rt == 1)
		return;
	int parent = rt >> 1;
	Tree[parent].val = max(Tree[parent << 1].val, Tree[parent << 1 | 1].val);
	updata(parent);
}

long long ans;

void query(int rt, int w)
{
	if (Tree[rt].val < w)
	{
		ans = -1;
		return;
	}
	if (Tree[rt].l == Tree[rt].r)
	{
		ans = Tree[rt].l;
		Tree[rt].val -= w;
		updata(rt);
		return;
	}
	if (Tree[rt << 1].val >= w)
		query(rt << 1, w);
	else
		query(rt << 1 | 1, w);
}


int main(void)
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int h, w, n;
	while (cin >> h >> w >> n)
	{
		if (h > n)//h可能很大,但只有n个公告,最多也就只能用n这么高的黑板
			h = n;
		buildTree(1, 1, h, w);
		while (n--)
		{
			cin >> w;
			query(1, w);
			cout << ans << endl;
		}
	}
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值