题意:有一块大小h*w的公告牌,可以在上面贴广告,每张广告大小为1*wi,优先贴在高处,左边,如果可以贴,输出贴在了第几排,否则输出-1
思路:线段树记录的是某个区间能张贴的最长广告长度,更新同时查询,可以张贴时:在l == r 的位置更新最底层的值,然后向上更新时取左右子区间的最大值
#include <stdio.h>
#include <string.h>
#define lson l, m, rt * 2
#define rson m + 1, r, rt * 2 + 1
using namespace std;
int max[200010*4];
void pushup(int rt)
{
max[rt] = max[rt * 2] > max[rt * 2 + 1] ? max[rt * 2] : max[rt * 2 + 1];
}
void build(int l, int r, int rt, int n)
{
if(l == r)
{
max[rt] = n;
return;
}
int m = (l + r) / 2;
build(lson, n);
build(rson, n);
pushup(rt);
}
int update(int w, int l, int r, int rt)
{
if(max[rt] < w) return -1;
if(l == r)
{
if(max[rt] >= w)
{
max[rt] -= w;
return l;
}
else
{
return -1;
}
}
int flag = -1, m = (l + r) / 2;
flag = update(w, lson); // 左半区间找到位置
if(flag < 0) //左半区间找不到位置
flag = update(w, rson);
pushup(rt);
return flag;
}
int main()
{
#ifdef LOCAL
freopen("data.in", "r", stdin);
#endif
int r, c, n;
while(scanf("%d%d%d", &r, &c, &n) != EOF)
{
if(r > n) r = n;
build(1, r, 1, c);
while(n--)
{
int w;
scanf("%d", &w);
printf("%d\n", update(w, 1, r, 1));
}
}
return 0;
}