链接: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 "); else printf("%d ", Query(1, 1, h, v)); } } return 0; }