題意:給一個長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;
}