题意:给一个长w宽h的板子,每次往上面贴一个长wi宽1的条子(不可旋转),共n个,每次贴的时候都贴在能贴的最上行的最左端,若贴不下就不贴
给出w,h,wi,n求每个帖子在第几行,若贴不下,输出-1
思路:使用最大值线段树记录每行剩余长度,树叶表示那一行的剩余长度。在每次贴的时候,若wi>根值,则树上所有叶子都比这个帖子小,故挂不下,输出-1。
若h>n,则说明多的行不需要,h=n即可,(所以说题目上的h<1e9是吓人的)(当时这里手滑写成了h<n结果re了一个晚上)
对于每次查询,使用深搜来找,找叶子后把叶子值改了,返回叶子的位置就是贴的行数了
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
struct segn
{
int mi;
}segt[200000*4];
void build(int h,int root,int st,int en)
{
if(st==en)
{
segt[root].mi=h;
return;
}
int mid=(st+en)/2;
build(h,root*2+1,st,mid);
build(h,root*2+2,mid+1,en);
segt[root].mi=h;
}
int adjust_elemt(const int addval,int st,int en,int root)
{
if(st==en)
{
segt[root].mi-=addval;
return st;
}
int mid=(st+en)/2,ret;
if(segt[2*root+1].mi>=addval)
ret=adjust_elemt(addval,st,mid,root*2+1);
else
ret=adjust_elemt(addval,mid+1,en,root*2+2);
segt[root].mi=max(segt[root*2+1].mi,segt[root*2+2].mi);
return ret;
}
int main()
{
int h,w,n,yes,cur;
while(~scanf("%d%d%d",&h,&w,&n))
{ if(h>n)h=n;
build(w,0,0,h-1);
for(int i=0;i<n;i++)
{scanf("%d",&cur);
if(cur>segt[0].mi)printf("-1\n");
else{yes=adjust_elemt(cur,0,h-1,0);printf("%d\n",yes+1);}
}
}
return 0;
}