hdu2795(线段树单点更新)

题目链接:hdu2795

/*线段树单点更新,求区间最大值
题目大意:有一块板子,长宽分别为W,H,然后有n块1*w海报
让你把这n快海报贴在这块板子上,尽量往板子的上方贴,同一行尽量往板子的左边贴。
对于第i块海报如果能够贴下则输出能贴在第几行,否则输出-1。

思路:利用线段树求区间的最大值;
maxx表示区间内能贴的海报的最大宽度
建树的时候要注意,heigh的范围特别大
当heigh>=m(m是海报的数量),要用m来建树
*/
#include<cstdio>
#include<algorithm>
using namespace std;

#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
const int N = 200005;
int sum[N<<2];//表示某行能贴的海报的宽度
void build(int wide, int l, int r, int rt)
{
    sum[rt] = wide;//初始化为wide,最开始板上未贴海报
    if(l == r) return ;
    int m = (l+r) >> 1;
    build(wide, lson);
    build(wide, rson);
}
void update(int num, int pos, int l, int r, int rt)
{
    if(l == pos && r == pos)
    {
        sum[rt] -= num;//该行贴上一个宽为num的海报
        return ;
    }
    int m = (l + r) >> 1;
    if(pos <= m) update(num, pos, lson);
    if(m < pos) update(num, pos, rson);
    sum[rt] = max(sum[rt<<1], sum[rt<<1|1]);//更新父节点
}
int query(int num, int l, int r, int rt)
{
    if(sum[rt] < num) return -1;
    if(l == r) return l;
    int m = (l + r) >> 1;
    if(sum[rt<<1] >= num)
        return query(num, lson);
    else
        return query(num, rson);
}
int main()
{
	int i,n,heigh,wide,num;
	while(~scanf("%d%d%d",&heigh,&wide,&n))
	{
	    heigh = min(heigh, n);
	    build(wide, 1, heigh, 1);
	    while(n--)
	    {
	        scanf("%d",&num);
	        int pos = query(num, 1, heigh, 1);
	        if(pos == -1) printf("-1\n");
	        else
	        {
	            printf("%d\n",pos);
	            update(num, pos, 1, heigh, 1);
	        }
	    }
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值