HDOJ 2795 Billboard

~~~题目链接~~~


题目大意:在一个高为h, 宽为w的面板上贴上n张海报, 每个海报的高都为1, 每张海报能尽可能的贴在高度最高的地方, 当同一个高度有多个地方可以贴海报时,贴在最左边, 现在求每个海报能贴在哪个高度。


思路:用线段树进行2分区间, 把高度看成区间。区间的高度为最小的(h, n), 注意n == 1时;


code:

#include <stdio.h>
#define N 200002
#define max(a,b) a>b? a:b
using namespace std;
struct node
{
    int id, w;
}t[4*N];
int h = 0, w = 0, n = 0, cnt = 0, flag = 0;
void build(int c, int l, int r)//区间的值存当前所有叶子节点中能剩余贴的地方的最大宽度
{
    int m = l+(r-l)/2;
    if(l == r)
    {
        t[c].id = cnt++;
        t[c].w = w;
        return ;
    }
    build(2*c, l, m);
    build(2*c+1, m+1, r);
    t[c].w = max(t[2*c].w, t[2*c+1].w);
}

int query(int c, int l, int r, int w)
{
    int num = -1;
    int m = l+(r-l)/2;
    if(t[c].w<w) return -1;
    if(l == r )
    {
        t[c].w -= w;
        return t[c].id;
    }
    if(t[2*c].w>=w) num = query(2*c, l, m, w);
    else if(t[2*c+1].w>=w) num = query(2*c+1, m+1, r, w);
    t[c].w = max(t[2*c].w, t[2*c+1].w);
    return num;
}

int main()
{
    int i = 0, min = 0, num[N];
    while(scanf("%d %d %d", &h, &w, &n) != EOF)
    {
        min = h<n? h:n;
        build(1, 1, min);
        for(i = 0; i<n; i++)
        {
            cnt = 0;
            int w = 0;
            scanf("%d", &w);
            flag = 0;
            num[i] = query(1, 1, min, w);
        }
        for(i = 0; i<n; i++)
        {
                if(num[i] == -1) printf("%d\n", num[i]);
                else
                        printf("%d\n", num[i]+1);
        }
    }
    return 0;
}

 

你可能感兴趣的:(HDOJ 2795 Billboard)