hdu~2795(线段树)

Billboard

第一眼看去这道题还真没看出来是线段树的题,可能是题目做的少吧。

题意:给你一个h*w大的墙,让你贴n张海报,每张海报规格是1*wi。尽可能的忘左上方贴,(上优先于左)

输出每张海报的行数,贴不下的输出-1

 (1 <= h,w <= 10^9; 1 <= n <= 200,000)  //因为最多n张海报,所以h的范围实际上是1~200,000


线段树的叶子存的h行位置,每个阶段存的是在该区间内有没有合适的位置。


0.0好像很难懂的样子,算了,还是在代码里注释清楚吧,上代码:


#include <stdio.h>
#include <iostream>
#define MAX 20000005

using namespace std;
struct ac
{
    int space;          //存的是在l~r区间内,剩余空间的最大值,初始为w
    int l,r;
}post[MAX];

int h,w,n;

inline int fmax(int a,int b)  
{
    return a>b?a:b;
}

void build(int l,int r,int k)   //标准的建树
{
    post[k].l=l;
    post[k].r=r;
    post[k].space=w;
    if(l==r)
        return ;
    int mid=(l+r)/2;
    build(l,mid,2*k);
    build(mid+1,r,2*k+1);
}

void insert(int x,int k)
{
    if(post[k].l==post[k].r)   //当遍历到叶子的时候
    {
        if(post[k].space>=x)    //如果剩余空间足够
        {
            post[k].space-=x;   //贴上海报,空间-x
            printf("%d\n",post[k].l);
        }
        else
            printf("-1\n");
        return ;
    }
    if(post[2*k].space>=x)  //如果左子节点的空间比x大
        insert(x,2*k);
    else
        insert(x,2*k+1);
    post[k].space=fmax(post[2*k].space,post[2*k+1].space);  //更新子节点之后,更新当前节点space值
}

int main()
{
    int i;
    while(scanf("%d %d %d",&h,&w,&n)!=EOF)
    {
        if(h>n)         // 这个地方得注意,因为最多n张海报,每张海报规格为1*wi
            h=n;
        build(1,h,1);   //建树
        while(n--)      //10^5
        {
            int x;
            scanf("%d",&x);
            insert(x,1);    //更新同时输出
        }
    }
    return 0;
}

总之感觉很神奇,这都能用线段树做!!



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值