题目意思大概就是在高h,宽w的板上贴n张海报(1 <= h,w <= 10^9; 1 <= n <= 200,000) 。 海报都是1单位高,海报尽量贴左上角的地方,给出海报的宽,输出海报贴在第几行。
#include<stdio.h>
#include<algorithm>
#define maxn 200000+10
using namespace std;
//因为贴海报都是从最左开始的,所以每行的可贴大小只要大于海报宽度就可以贴,所以只需要单点更新就好
//因为要是海报的宽度大于每行的宽度无论也贴不上去,所以n张海报最多占用的行数就是n,所以线段树最大的容量只需要n>>2, 不需要h行
typedef struct
{
int l,r,ms; //l表示该节点的最小行数,r表示最大行数,ms表示在这些行中最大容量
}node;
node num[maxn<<2];
int ceng;
void build(int pos,int l,int r,int val)
{
num[pos].l=l;
num[pos].r=r;
num[pos].ms=val;
if(l==r)
return ;
int mid=(l+r)>>1;
build(pos<<1,l,mid,val);
build(pos<<1|1,mid+1,r,val);
}
void update(int pos,int l,int r,int need)
{
if(num[pos].ms<need)
return ;
if(l==r)
{
num[pos].ms-=need;
ceng=l;
return ;
}
int mid=(l+r)>>1;
if(num[pos<<1].ms>=need)
update(pos<<1,l,mid,need); //尽量从左上角开始贴,所以优先更新左子树
else
update(pos<<1|1,mid+1,r,need);
num[pos].ms=max(num[pos<<1].ms,num[pos<<1|1].ms); //父节点的最大容量为左右子树的最大容量
}
int main()
{
int h,w,n,i,need;
while(scanf("%d%d%d",&h,&w,&n)!=EOF)
{
build(1,1,min(n,h),w); //构造的层数是海报数和行数的最小值
for(i=0;i<n;i++)
{
scanf("%d",&need);
ceng=-1;
update(1,1,min(n,h),need);
printf("%d\n",ceng);
}
}
return 0;
}