题意:
有一个 h * w 的矩形,要用 1 * w[i] 的小矩形去覆盖它,覆盖的原则是先 topmost,再 leftmost,并且不能覆盖现有的矩形。
给出 n 组询问,问当前的小矩形能放在哪一行。
还真没看出来是棵线段树...
不过一说是线段树,就十分合理了,就是一个询问区间最大值的问题。
所以这道题的关键就是:看出来这是个线段树!
此外,细节方面的处理就是 n 和 h 取个最小值,因为对 n 个矩形有意义的覆盖范围就是最上面 n 行。
(一遍 A 真开心)
AC代码如下:
#include <bits/stdc++.h>
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define maxn 200010
struct node {
int l, r, max, id;
}tr[maxn * 4];
int h, w, n, tot;
inline max(int a, int b) { return a > b ? a : b; }
void push_up(int rt) {
tr[rt].max = max(tr[lson].max, tr[rson].max);
}
void build(int rt, int l, int r) {
tr[rt].l = l; tr[rt].r = r; tr[rt].max = w;
if (l == r) { tr[rt].id = ++tot; return; }
int mid = l + r >> 1;
build(lson, l, mid); build(rson, mid + 1, r);
}
void query(int rt, int x) {
if (tr[rt].l == tr[rt].r) {
printf("%d\n", tr[rt].id);
tr[rt].max -= x;
return;
}
if (tr[lson].max >= x) query(lson, x);
else query(rson, x);
push_up(rt);
}
void work() {
h = h < n ? h : n;
tot = 0;
build(1, 1, h);
for (int i = 0; i < n; ++i) {
int x;
scanf("%d", &x);
if (tr[1].max < x) { printf("-1\n"); continue; }
query(1, x);
}
}
int main() {
while (scanf("%d%d%d", &h, &w, &n) != EOF) work();
return 0;
}