hdu2759 Billbord(线段树)

题意:给一个长w宽h的板子,每次往上面贴一个长wi宽1的条子(不可旋转),共n个,每次贴的时候都贴在能贴的最上行的最左端,若贴不下就不贴

           给出w,h,wi,n求每个帖子在第几行,若贴不下,输出-1

思路:使用最大值线段树记录每行剩余长度,树叶表示那一行的剩余长度。在每次贴的时候,若wi>根值,则树上所有叶子都比这个帖子小,故挂不下,输出-1。

           若h>n,则说明多的行不需要,h=n即可,(所以说题目上的h<1e9是吓人的)(当时这里手滑写成了h<n结果re了一个晚上

           对于每次查询,使用深搜来找,找叶子后把叶子值改了,返回叶子的位置就是贴的行数了

#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
    struct segn
    {
        int mi;
    }segt[200000*4];
    void build(int h,int root,int st,int en)
    {
        if(st==en)
        {
            segt[root].mi=h;
            return;
        }
        int mid=(st+en)/2;
        build(h,root*2+1,st,mid);
        build(h,root*2+2,mid+1,en);
        segt[root].mi=h;
    }
    int adjust_elemt(const int addval,int st,int en,int root)
    {
            if(st==en)
            {
                segt[root].mi-=addval;
                return st;
            }
        int mid=(st+en)/2,ret;
        if(segt[2*root+1].mi>=addval)
        ret=adjust_elemt(addval,st,mid,root*2+1);
        else
        ret=adjust_elemt(addval,mid+1,en,root*2+2);
        segt[root].mi=max(segt[root*2+1].mi,segt[root*2+2].mi);
        return ret;
    }

    int main()
    {
        int h,w,n,yes,cur;

        while(~scanf("%d%d%d",&h,&w,&n))
        {    if(h>n)h=n;
            build(w,0,0,h-1);


            for(int i=0;i<n;i++)
            {scanf("%d",&cur);
                if(cur>segt[0].mi)printf("-1\n");
                else{yes=adjust_elemt(cur,0,h-1,0);printf("%d\n",yes+1);}

            }
        }
        return 0;
    }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值