题目请点我
题解:
当使用普通数据结构不能满足要求时,就要想到其他的数据结构来维护。这道题用线段树维护查找,可以满足O(NlogN)的时间复杂度。
注意这句话:When someone puts a new announcement on the billboard, she would always choose the topmost possible position for the announcement. Among all possible topmost positions she would always choose the leftmost one.,与之对应的是线段树中尽量让左子树先消耗,保存的数值是当前行所剩余的宽度。
另外应该注意到在构建线段树的时候不能简单以1~H作为边界,因为H的取值范围高达10^9,应该取H和N两者中的较小值,否则会RE。
代码实现:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define MAX 300000
using namespace std;
int N;
int H,W;
int segTree[MAX<<2];
void pushUp(int root);
void build(int root,int l,int r);
void query(int val,int l,int r,int root);
int main()
{
while( scanf("%d%d%d",&H,&W,&N) != EOF ){
//H的取值范围是10^9,数组不可能有那么大,
//而且若N<H,则最多也就使用N行,所以取最小值
H = min(H,N);
build(1,1,H);
for( int i = 0; i < N; i++ ){
int tmp;
scanf("%d",&tmp);
if( tmp > segTree[1] ){
printf("-1\n");
}
else{
query(tmp,1,H,1);
}
}
}
return 0;
}
void build(int root,int l,int r){
if( l == r ){
segTree[root] = W;
return ;
}
int mid = (l+r)>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
pushUp(root);
return ;
}
void pushUp(int root){
segTree[root] = max(segTree[root<<1],segTree[root<<1|1]);
}
void query(int val,int l,int r,int root){
//也可以作为返回值返回
if( l == r ){
segTree[root] -= val;
printf("%d\n",l);
return ;
}
int mid = (l+r)>>1;
if( segTree[root<<1] >= val ){
query(val,l,mid,root<<1);
}
else{
query(val,mid+1,r,root<<1|1);
}
pushUp(root);
return ;
}