题目链接:https://vjudge.net/problem/Gym-100623B
题意:有一个h层的柜子,每层只能放重量不超过w的东西,现在给你n个物体,从上往下放,让你输出每一个物体放在第几层,如果放不下就输出-1
解析:一开始我们队的想法是用优先队列找最小值,不过发现当前的最小值不一定是不是层数最小的那个,最后觉得像线段树,也就是区间查询最小值,判断那个区间(1~h)是否能放a[i]上去,反正就这样一直维护就好了,不过要注意,其实他层数最大是n(2e5),而不会达到1e9,所以一开始需要取一下最小值,不然会RE
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 1e6+100;
const int inf = 0x7fffffff;
struct node
{
int l,r;
int minn;
}t[4*maxn];
int h,w,n;
void push_up(int i)
{
t[i].minn = min(t[i<<1].minn,t[i<<1|1].minn);
}
void build(int i,int l,int r)
{
t[i].l = l;
t[i].r = r;
if(l==r)
{
t[i].minn = 0;
return ;
}
int mid = (l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
push_up(i);
}
int query(int i,int l,int r,int v)
{
if(t[i].minn+v>w)
return -1;
if(l==r)
{
t[i].minn += v;
return l;
}
int ans;
if(t[i<<1].minn + v <= w)
ans = query(i<<1,l,(l+r)/2,v);
else
ans = query(i<<1|1,(l+r)/2+1,r,v);
push_up(i);
return ans;
}
int main(void)
{
freopen("billboard.in","r",stdin);
freopen("billboard.out","w",stdout);
scanf("%d %d %d",&h,&w,&n);
int tt = min(h,n);
build(1,1,tt);
while(n--)
{
int x;
scanf("%d",&x);
printf("%d\n",query(1,1,tt,x));
}
return 0;
}