题意:有h*w的 广告板子,现在要添加n次,的广告,每个广告宽度都为1,而且都只能横着放,依次输入每个广告的长度 x,问广告插入在哪一行,插不了输出-1
解法:线段树 ,单点更新,找还剩下的地方的最大值,update就直接在 query里进行了
#include <stdio.h>
#include <string.h>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int N=222222;
//一开始想不明白肯定会爆
//n次放入可以放在重复层,而且 n 一定是小于等于h的
//再长的h也是浪费,所以最大用2X10^5,不用10^9
int Max[N<<2];
int h,w,n;
void PushUP(int rt){
Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
}
void build(int l,int r,int rt){
Max[rt]=w;
if(l==r) return ;
int m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
}
int query(int x,int l,int r,int rt){
//x 新的一行
if(l==r){
Max[rt]-=x;
return l;//返回这一行
}
int m=(l + r)>>1;
int ret=0;
// 如果 左边比 x大,往左走
if(Max[rt<<1]>= x)
ret=query(x,l,m,rt<<1);
else ret=query(x,m+1,r,rt<<1|1);
PushUP(rt);
return ret;
}
int main()
{
while(~scanf("%d%d%d",&h,&w,&n))
{
// n 为添加的长度,h为行数
// n一定是小于等于h的可以减少很多没用的行数
if(h>n) h=n;
build(1,h,1);
while(n--)
{
int x;
scanf("%d",&x);
// Max[1] 最大的一行的长度
if(Max[1]<x) printf("-1\n");
else printf("%d\n",query(x,1,h,1));
}
}
return 0;
}