hdu 2795(线段树更新单个节点)

题目链接:点击打开链接

题意:给你一个高位h宽为w的木板,现在给你一些通知条高度为1,宽度为wi,现在要尽可能的将每一个通知条往木板的最上层放,并尽量向当前层的左边放(从最高层到最低层的按1---min(h,n)开始编号),对于每输入的一个纸条输出其可以摆放的最高层次,若该纸条不能被放,那么输出-1


分析:由于h和w均为10^9,如果想暴力的话,不但会超时而且还会超内存,这里我们可以往线段树上去想,由于每个纸条能够放在当前行的条件是当前行的剩余的宽度要大于纸条的宽度,我们求的是每个纸条对应的行,那么我们就可以用行来作为区间用来更新,查找的时候尽可能的向着左子树查找,因为他的行号最小对应的层数最高


代码:


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int N = 222225;
int ans;
struct node
{
	int l,r;
	int maxw;//表示行l到r中每行剩余的区间长度的最大值
}tree[N*4];

void bulid(int rt, int l, int r,int w)
{
	tree[rt].l=l;
	tree[rt].r=r;
	tree[rt].maxw=w;
	if(l==r)
		return;
	int mid =(l+r)/2;
	bulid(2*rt,l,mid,w);
	bulid(2*rt+1,mid+1,r,w);
}

void search(int rt,int x)
{
	if(tree[rt].l==tree[rt].r)
	{
		 tree[rt].maxw -= x;
	     ans = tree[rt].l;
		 return;
	}
   if(tree[2*rt].maxw>=x)
	     search(2*rt,x);
   else  if(tree[2*rt+1].maxw >=x)search(2*rt+1,x);
   tree[rt].maxw = tree[2*rt].maxw>tree[2*rt+1].maxw ? tree[2*rt].maxw : tree[2*rt+1].maxw;
}
   
int main ()
{
	int h, w, n,i,x;
	while(scanf("%d%d%d",&h,&w,&n)!=EOF)
	{
		if(h>n)h= n;//至多需要的行数
		bulid(1,1,h,w);
		for(i=0;i<n;i++)
		{
			scanf("%d",&x);
			if(tree[1].maxw<x) puts("-1");//若剩下的所有中所剩下的宽度的最大值<x那么该通知放不了,输出-1
		    else	
			{
		    	search(1,x);
				printf("%d\n",ans);//返回行号,id为-1则表示长度为x的纸条放不了       
			}
		}
	}
	return 0;
}
			




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值