Hdu 2795 Billboard

题目大意:给定一个h*w的宣传板,然后在给定n个1*wi的小广告,问这些小广告在宣传板的第几行(因为每个小广告都想放在最上面,且最靠左边的位置)。

题目分析:刚开始想到的是将整个宣传板看做时一个1~h*w的区间,然后用1*wi的小广告来按照题意来更新这段区间。但是这种想法很天真。操作性压根都没用。所以不妨换一种思路。将宣传版的每一行都看做是一个点,这样整个宣传板就可以看做是一个1~h的区间,然后每个叶子节点维护的是当前行还剩下的长度。父亲节点维护的是子节点剩下的最长的长度(这样可以减枝)。这样就可以用线段树解决问题了。将update放在query中进行。注意,最多有20w个传单,也就是最多会占用20w行的宣传版。发现只要想的大致方向对,题目都会隐藏的对你说如何做。这就是刘未鹏说的好题吧。

下面是代码:

/*Hdu 2795 Billboard
    segment tree
*/
#include <stdio.h>
#include <algorithm>
using namespace std;
#define maxn 210000
int re[maxn<<2];
int h,w,n;
void push_up(int rt)
{
    re[rt] = max(re[rt<<1],re[rt<<1|1]);
}
void build(int l,int r,int rt)
{
    if(l == r)
    {
        re[rt] = w;
        return ;
    }
    int mid = (l + r) >> 1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    push_up(rt);
}
int query(int v,int l,int r,int rt)
{
    if(v > re[rt]) return -1;
    if(l == r)
    {
        re[rt] -= v;
        return l;
    }
    int mid = (l + r) >> 1;
    int ret = -1;
    if(v <= re[rt<<1]) ret = query(v,l,mid,rt<<1);
    else if(v <= re[rt<<1|1]) ret = query(v,mid+1,r,rt<<1|1);
    push_up(rt);
    return ret;
}
int main()
{
    while(~scanf("%d%d%d",&h,&w,&n))
    {
        build(1,min(h,n),1);
        for(int i = 0; i < n; i++)
        {
            int x;
            scanf("%d",&x);
            int ans = query(x,1,min(n,h),1);
            printf("%d\n",ans);
        }
    }
    return 0;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值