• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
ACM s1124yy
守りたいものが 強くさせること
博客园    首页    新随笔    联系   管理     

HDU 2795 Billboard(区间求最大值的位置update的操作在query里做了)

Billboard

通过这题,我知道了要活用线段树的思想,而不是拘泥于形式, 就比如这题 显然更新和查询放在一起很简单 但如果分开写 那么我觉得难度会大大增加

【题目链接】Billboard

【题目类型】区间求最大值的位置update的操作在query里做了

&题意:

h*w的木板,放进一些1*L的物品,求每次放空间能容纳且最上边的位子

&题解:

思路:每次找到最大值的位子,然后减去L
线段树功能:query
区间求最大值的位置(直接把update的操作在query里做了)

【时间复杂度】\(O(nlogn)\)

&代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 200000 + 9 ;
int h,w,n;
int seg[maxn<<2];
inline void PushUp(int rt)
{
	seg[rt]=max(seg[rt<<1],seg[rt<<1|1]);
}
void Build(int b,int e,int rt)
{
	if (b==e){
		seg[rt]=w;
		return;
	}
	int m=b+e>>1;
	Build(b,m,rt<<1);
	Build(m+1,e,rt<<1|1);
	PushUp(rt);
}
//把更新和查询放在了一起
int Query(int xx,int b,int e,int rt)
{
	if (b==e){
		seg[rt]-=xx;
		return b;
	}
	int m=b+e>>1;
	int re=0;
	//这里保证了先从小的序号开始找
	if (seg[rt<<1]>=xx)
		re=Query(xx,b,m,rt<<1);
	else
		re=Query(xx,m+1,e,rt<<1|1);
	PushUp(rt);
	return re;
}
void Solve()
{
	while(~scanf("%d%d%d",&h,&w,&n)){
		h=min(h,n);
		Build(1,h,1);
		for(int i=0;i<n;i++){
			int t;
			scanf("%d",&t);
			if (seg[1]<t) puts("-1");
			else {
				printf("%d\n",Query(t,1,h,1));
			}
		}
	}
}
int main()
{
	Solve();
	return 0;
}
posted @ 2016-12-26 16:17  s1124yy  阅读(204)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3