链接: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;
}