读完题后我是没想出这个题和线段树有什么关系
看别人写的解题报告才知道可以把每行看成线段树的叶子
记录每片叶子的剩余空间,而根节点中保存的是叶子节点最大的剩余空间
每次判断给定的宽度从根节点能否插入,若左子数可以插则优先插入左子树
这样就可以保证每次插入都插在最上面
这个题的输出比较大,千万不能用cout,我就是因为用cout一直TLE!
代码如下:
#include <cstdio>
#include <iostream>
#include <algorithm>
#define MAXN 200010
#define LL long long
using namespace std;
int w, Max[MAXN<<1];
void pushUp(int rt) {
Max[rt] = max(Max[rt<<1], Max[rt<<1|1]);
}
void build(int w, int l, int r, int rt) {
Max[rt] = w;
if(l == r)
return ;
int m = (l+r)>>1;
build(w, l, m, rt<<1);
build(w, m+1, r, rt<<1|1);
}
int query(int x, int l, int r, int rt) {
if(l == r) {
Max[rt] -= x;
return l;
}
int ans;
int m = (l+r)>>1;
if(Max[rt<<1] >= x)
ans = query(x, l, m, rt<<1);
else ans = query(x, m+1, r, rt<<1|1);
pushUp(rt);
return ans;
}
int main(void) {
int h, n, w;
while(~scanf("%d%d%d", &h, &w, &n)) {
h = min(h, n);
build(w, 1, h, 1);
while(n--) {
int x;
scanf("%d", &x);
if(x > Max[1])
printf("-1\n");
else printf("%d\n", query(x, 1, h, 1));
}
}
return 0;
}