题目链接:hdu2795
/*线段树单点更新,求区间最大值
题目大意:有一块板子,长宽分别为W,H,然后有n块1*w海报
让你把这n快海报贴在这块板子上,尽量往板子的上方贴,同一行尽量往板子的左边贴。
对于第i块海报如果能够贴下则输出能贴在第几行,否则输出-1。
思路:利用线段树求区间的最大值;
maxx表示区间内能贴的海报的最大宽度
建树的时候要注意,heigh的范围特别大
当heigh>=m(m是海报的数量),要用m来建树
*/
#include<cstdio>
#include<algorithm>
using namespace std;
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
const int N = 200005;
int sum[N<<2];//表示某行能贴的海报的宽度
void build(int wide, int l, int r, int rt)
{
sum[rt] = wide;//初始化为wide,最开始板上未贴海报
if(l == r) return ;
int m = (l+r) >> 1;
build(wide, lson);
build(wide, rson);
}
void update(int num, int pos, int l, int r, int rt)
{
if(l == pos && r == pos)
{
sum[rt] -= num;//该行贴上一个宽为num的海报
return ;
}
int m = (l + r) >> 1;
if(pos <= m) update(num, pos, lson);
if(m < pos) update(num, pos, rson);
sum[rt] = max(sum[rt<<1], sum[rt<<1|1]);//更新父节点
}
int query(int num, int l, int r, int rt)
{
if(sum[rt] < num) return -1;
if(l == r) return l;
int m = (l + r) >> 1;
if(sum[rt<<1] >= num)
return query(num, lson);
else
return query(num, rson);
}
int main()
{
int i,n,heigh,wide,num;
while(~scanf("%d%d%d",&heigh,&wide,&n))
{
heigh = min(heigh, n);
build(wide, 1, heigh, 1);
while(n--)
{
scanf("%d",&num);
int pos = query(num, 1, heigh, 1);
if(pos == -1) printf("-1\n");
else
{
printf("%d\n",pos);
update(num, pos, 1, heigh, 1);
}
}
}
return 0;
}