HDU2795Billboard

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

分析:

题目大意是给一个h*w的公告牌,h是高度,w是宽度,一个单位高度1为一行,然后会有一些公告贴上去,公告是1*wi大小的长纸条,优先贴在最上面并且最左边的位置,如果没有空间贴得下,就输出-1,可以的话,就输出所贴的位置(第几行)。

叶节点[x,x]表示board的第x行还可以放置的长度,区间[a,b]表示第a行到b行中剩下空间最大的那一行是多少,如果要把长w的公告放入 board时就是update,优先往左子树走(如果左子树的空间足够的话),一直走到叶节点,更新这个叶节点剩下的长度,然后再向上更新。

#include <iostream>
#include <cstdio>

using namespace std;
const int maxn = 200010;
int w;
struct Node
{
    int l,r,mid;
    int max;
}d[maxn*3];
void build(int L,int R,int rt)
{
    d[rt].l = L;
    d[rt].r = R;
    d[rt].mid = (L+R)/2;
    d[rt].max = w;
    if (L==R) return;
    build(L,(L+R)/2,rt*2);
    build((L+R)/2+1,R,rt*2+1);
}
int update(int board,int rt)
{
    if (d[rt].l == d[rt].r)
    {
        d[rt].max -= board;
        return d[rt].l;
    }
    int ret;
    if (d[rt*2].max >= board) ret = update(board,rt*2);
    else ret = update(board,rt*2+1);
    d[rt].max = max(d[rt*2].max,d[rt*2+1].max);
    return ret;
}
int main()
{
    int h,n,board;
    while (scanf("%d%d%d",&h,&w,&n)==3)
    {
        build(1,min(h,n),1);
        while(n--)
        {
            scanf("%d",&board);
            if (d[1].max < board) printf("-1\n");
            else printf("%d\n",update(board,1));
        }
    }
    return 0;
}


你可能感兴趣的:(HDU2795Billboard)