题目链接:点击打开链接
题意:给你一个高位h宽为w的木板,现在给你一些通知条高度为1,宽度为wi,现在要尽可能的将每一个通知条往木板的最上层放,并尽量向当前层的左边放(从最高层到最低层的按1---min(h,n)开始编号),对于每输入的一个纸条输出其可以摆放的最高层次,若该纸条不能被放,那么输出-1
分析:由于h和w均为10^9,如果想暴力的话,不但会超时而且还会超内存,这里我们可以往线段树上去想,由于每个纸条能够放在当前行的条件是当前行的剩余的宽度要大于纸条的宽度,我们求的是每个纸条对应的行,那么我们就可以用行来作为区间用来更新,查找的时候尽可能的向着左子树查找,因为他的行号最小对应的层数最高
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 222225;
int ans;
struct node
{
int l,r;
int maxw;//表示行l到r中每行剩余的区间长度的最大值
}tree[N*4];
void bulid(int rt, int l, int r,int w)
{
tree[rt].l=l;
tree[rt].r=r;
tree[rt].maxw=w;
if(l==r)
return;
int mid =(l+r)/2;
bulid(2*rt,l,mid,w);
bulid(2*rt+1,mid+1,r,w);
}
void search(int rt,int x)
{
if(tree[rt].l==tree[rt].r)
{
tree[rt].maxw -= x;
ans = tree[rt].l;
return;
}
if(tree[2*rt].maxw>=x)
search(2*rt,x);
else if(tree[2*rt+1].maxw >=x)search(2*rt+1,x);
tree[rt].maxw = tree[2*rt].maxw>tree[2*rt+1].maxw ? tree[2*rt].maxw : tree[2*rt+1].maxw;
}
int main ()
{
int h, w, n,i,x;
while(scanf("%d%d%d",&h,&w,&n)!=EOF)
{
if(h>n)h= n;//至多需要的行数
bulid(1,1,h,w);
for(i=0;i<n;i++)
{
scanf("%d",&x);
if(tree[1].maxw<x) puts("-1");//若剩下的所有中所剩下的宽度的最大值<x那么该通知放不了,输出-1
else
{
search(1,x);
printf("%d\n",ans);//返回行号,id为-1则表示长度为x的纸条放不了
}
}
}
return 0;
}