问题:
蒜厂有一个 h×w 的矩形公告板,其中 h 是高度,w 是宽度。
现在有若干张 1×Wi 的公告, Wi 是宽度,公告只能横着放,即高度为 1 的边垂直于水平面,且不能互相有重叠,每张公告都要求尽可能的放在最上面的合法的位置上。
若可以放置,输出每块可放置的位置的行号;若不存在,输出 −1。行号由上至下分别为 1,2,…,h。
输入格式
第一行三个整数 h,w,n (1≤h,w≤10^9;1≤n≤200,000) 。
接下来 n 行,每行一个整数 Wi(1≤Wi≤109) 。
输出格式
输出n 行,一行一个整数。
样例输入:
3 5 5
2
4
3
3
3
1
2
3
4
5
6
样例输出
1
2
1
3
-1
AC代码:线段树
#include<bits/stdc++.h>
using namespace std;
int s[1000010 * 5];
int h,w,n;
void up(int p){
s[p] = max(s[p * 2],s[p * 2 + 1]);
}
void BuildTree(int p,int l,int r,int x){
if(l == r){
s[p] = x;
return ;
}
int mid = (l + r) / 2;
if(l <= mid){
BuildTree(p * 2,l,mid,x);
}
if(r > mid){
BuildTree(p * 2 + 1,mid + 1,r,x);
}
up(p);
}
void modify(int p,int l,int r,int x,int c){
if(l == r){
s[p] += c;
return ;
}
int mid = (l + r) / 2;
if(x <= mid){
modify(p * 2,l,mid,x,c);
}
else{
modify(p * 2 + 1,mid + 1,r,x,c);
}
up(p);
}
int query(int p,int l,int r,int x,int y){
if(x <= l && y >= r){
return s[p];
}
int mid = (l + r) / 2;
int res = 0;
if(x <= mid){
res = max(res,query(p * 2,l,mid,x,y));
}
if(y > mid){
res = max(res,query(p * 2 + 1,mid + 1,r,x,y));
}
return res;
}
void getVal(int p,int l,int r,int x){
while(l < r){
int mid = (l + r) / 2;
if(x <= query(1,1,h,l,mid)){
r = mid;
}
else if(x <= query(1,1,h,mid + 1,r)){
l = mid + 1;
}
else{
break;
}
}
if(l == r){
modify(1,1,h,l,-x);
printf("%d\n",l);
}
else{
printf("-1\n");
}
}
int main(){
scanf("%d%d%d",&h,&w,&n);
BuildTree(1,1,h,w);
for(int i=1;i<=n;++i){
int x;
scanf("%d",&x);
getVal(1,1,h,x);
}
return 0;
}