题目大意:在一块h层的广告牌上面贴广告,每个广告有一层宽,每个广告尽量往上往左贴。问贴的广告在第几层。
做法:这道题很机智的可以用线段树,把 1~h 层看作 线段 1~h ,树上每个节点记录线段的剩余长度最大值。贴广告时,若广告长度>左儿子节点,则进入做子树,否则看右儿子是否符合要求,若符合,则进入右子树。
以下是代码:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
int maxx[1000000];
int ans;
void pushup(int o)
{
maxx[o]=max(maxx[o*2],maxx[o*2+1]);
}
void build(int o,int L,int R,int w)
{
int ls=o*2,rs=o*2+1,m=L+(R-L)/2;
if(L==R){
maxx[o]=w;
return ;
}
build(ls,L,m,w);
build(rs,m+1,R,w);
pushup(o);
}
void update(int o,int L,int R,int wi)
{
int ls=o*2,rs=o*2+1,m=L+(R-L)/2;
if(L==R){
maxx[o]-=wi;
ans=L;
return ;
}
if(maxx[ls]>=wi)
update(ls,L,m,wi);
else if(maxx[rs]>=wi)
update(rs,m+1,R,wi);
pushup(o);
}
int main()
{
//freopen("in.txt","r",stdin);
int h,w,n;
while(scanf("%d%d%d",&h,&w,&n)!=EOF){
memset(maxx,0,sizeof(maxx));
if(h>200000)h=200000; //这里很重要。。不然数组会爆炸RE
build(1,1,h,w);
while(n--){
ans=-1;
int x;
scanf("%d",&x);
update(1,1,h,x);
printf("%d\n",ans);
}
}
return 0;
}