HDU-2795-Billboard

链接:https://vjudge.net/problem/HDU-2795#author=10152130143

题意:

在学校的入口处有一个巨大的矩形广告牌,高为h,宽为w。所有种类的广告都可以贴,比如ACM的广告啊,还有餐厅新出了哪些好吃的,等等。。
 
在9月1号这天,广告牌是空的,之后广告会被一条一条的依次贴上去。
 
每张广告都是高度为1宽度为wi的细长的矩形纸条。
 
贴广告的人总是会优先选择最上面的位置来帖,而且在所有最上面的可能位置中,他会选择最左面的位置,而且不能把已经贴好的广告盖住。
如果没有合适的位置了,那么这张广告就不会被贴了。
 
现在已知广告牌的尺寸和每张广告的尺寸,求每张广告被贴在的行编号。

思路:

线段树,以行数建树,每个位置对应当前行所剩的最大的空间。

将最大空间记录。

优先往左边查找大的空间。直到找到,同时找到后更新最大值。

代码:

#include <iostream>
#include <memory.h>
#include <vector>
#include <map>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <queue>
#include <string>
#include <stack>
#include <iterator>
#include <stdlib.h>
#include <time.h>
#include <assert.h>

using namespace std;
typedef long long LL;

const int MAXN = 2e5 + 10;

int segment[MAXN*4];
int a[MAXN];
int h, w, n;

void Build(int root, int l, int r)
{
    segment[root] = w;
    if (l == r)
        return;
    int mid = (l+r)/2;
    Build(root<<1, l, mid);
    Build(root<<1|1, mid+1, r);
}

int Query(int root, int l, int r, int v)
{
    if (l == r)
    {
        segment[root] -= v;
        return l;
    }
    int mid = (l+r)/2;
    int res = 0;
    if (segment[root<<1] >= v)
        res = Query(root<<1, l, mid, v);
    else
        res = Query(root<<1|1, mid+1, r, v);
    segment[root] = max(segment[root<<1], segment[root<<1|1]);
    return res;
}

int main()
{
    while (~scanf("%d%d%d", &h, &w, &n))
    {
        if (h > n)
            h = n;
        Build(1, 1, h);
        int v;
        for (int i = 1;i <= n;i++)
        {
            scanf("%d", &v);
            if (segment[1] < v)
                printf("-1\n");
            else
                printf("%d\n", Query(1, 1, h, v));
        }
    }

    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/YDDDD/p/10674639.html