首页 > 代码库 > HDU 2795 Billboard (线段树 单点更新 区间求最大值)

HDU 2795 Billboard (线段树 单点更新 区间求最大值)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2795

题意:有一块h*w 的广告版,有n块1*w[i]的广告,就着放广告尽量在顶上,尽量先放左边的原则,问在第几行能把广告放下,如果放不下,就打印-1;


思路:我们可以根据每一行建树,每一个子叶表示每一行的容量,而节点存放子节点的最大值,然后从最顶到底,快速查找能存放下广告的一行。

总之还是简单的线段树问题,难点在于抽象模型。


#include <iostream>
#include <cstdio>
#define MID (l + r) >> 1
#define LS rt << 1
#define RS rt << 1 | 1
#define LSON l,m,rt << 1
#define RSON m + 1,r,rt << 1 | 1
#define MAX 999999

using namespace std;

int imax[MAX << 2];

inline void pushup(int rt)
{
    imax[rt] = max(imax[LS],imax[RS]);
}

void build(int w,int l,int r,int rt)
{

    if(l == r)
    {
        imax[rt] = w;
        return ;
    }

    int m = MID;

    build(w,LSON);
    build(w,RSON);

    pushup(rt);
}

int query(int x,int l,int r,int rt)
{
    if(l == r)
    {
        imax[rt] -= x;
        return l;
    }

    int m = MID;

    int ret = (imax[LS] >= x) ? query(x,LSON) : query(x,RSON);

    pushup(rt);

    return ret;
}

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

    while(~scanf("%d%d%d",&h,&w,&n))
    {
        //优化:如果空间远远更能够h>n,那么就让h=n(一行一条广告)
        if(h > n)
            h = n;
        build(w,1,h,1);

        while(n--)
        {
            int x;
            scanf("%d",&x);

            if(imax[1] < x)    //如果最顶端没有位置
                puts("-1");
            else
                printf("%d\n",query(x,1,h,1));
        }
    }
    return 0;
}


HDU 2795 Billboard (线段树 单点更新 区间求最大值)