题意:一个公告板,高h,宽w。往上面贴n张公告,每张公告高为1,宽为wi,每次总是贴在尽可能靠上的位置中尽可能靠左的位置,不能覆盖之前的公告。输出每次公告贴在“第几行”,如果贴不下输出-1。
思路:线段树(单点更新)。节点数是min(h,n),内容是区间中剩余宽度的最大值,因为至多只有n张,那么如果“第n行”都贴不下的话,下面也贴不下。其实这题的更新和查询是一体的,直接写为一个函数了。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctype.h>
#define ll long long
using namespace std;
struct node{
int l; int r;
int val;
};
node tree[800010];
int h,w,n;
void build_tree(int n,int l,int r){
tree[n].l=r; tree[n].r=r; tree[n].val=w;
if(l==r)return;
int mid=(l+r)/2;
build_tree(n*2,l,mid);
build_tree(n*2+1,mid+1,r);
}
int update(int n,int l,int r,int v){
if(tree[n].val<v){
return -1;
}
if(l==r){
tree[n].val-=v;
return tree[n].l;
}
int mid=(l+r)/2;
int re;
if(tree[n*2].val>=v){
re=update(n*2,l,mid,v);
}else{
re=update(n*2+1,mid+1,r,v);
}
tree[n].val=max(tree[n*2].val,tree[n*2+1].val);
return re;
}
int main(){
while(cin>>h>>w>>n){
int R=min(n,h);
build_tree(1,1,R);
for(int i=1;i<=n;i++){
int a;
scanf("%d",&a);
int ans=update(1,1,R,a);
printf("%d\n",ans);
}
}
return 0;
}