有一塊高 h、寬 w 的廣告牌(h, w ≤ 10^9)。依次放入 n 張寬度為 w_i 的單位高度廣告(n ≤ 200,000)。放置規則:
本質上是對每一行維護「剩餘可用寬度」,每次查詢:找到第一個剩餘寬度 ≥ w_i 的行,並扣減該寬度。
min(h, n) 行#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 200005;
struct Node {
int l, r;
int maxWidth; // 區間最大剩餘寬度
} seg[MAXN << 2];
int h, w, n;
void build(int l, int r, int rt) {
seg[rt].l = l; seg[rt].r = r;
if (l == r) {
seg[rt].maxWidth = w;
return;
}
int mid = (l + r) >> 1;
build(l, mid, rt << 1);
build(mid + 1, r, rt << 1 | 1);
seg[rt].maxWidth = max(seg[rt << 1].maxWidth, seg[rt << 1 | 1].maxWidth);
}
// 查詢並更新:找到第一個能放下 width 的行
int query(int width, int rt) {
if (seg[rt].l == seg[rt].r) {
seg[rt].maxWidth -= width;
return seg[rt].l;
}
if (seg[rt << 1].maxWidth >= width)
return query(width, rt << 1);
else
return query(width, rt << 1 | 1);
}
int main() {
while (scanf("%d%d%d", &h, &w, &n) == 3) {
int rows = min(h, n);
build(1, rows, 1);
while (n--) {
int width; scanf("%d", &width);
if (width > seg[1].maxWidth) {
puts("-1");
} else {
int row = query(width, 1);
printf("%d\n", row);
}
}
}
return 0;
}
rows = min(h, n),否則構建樹會 MLE/TLE