题目大意:有一块K*W的广告牌,寻找1*L的广告的最大粘贴位置。
算法思想:
主要使用线段树的,查询和更新操作。初始时建立一个有h个叶子节点的线段树,每个节点的之都为W,然后进行查询操做,查询每个广告的宽度是否满足Max[1],不满足是输出-1,满足时是输出最优行号,每次查询是伴随着要对线段树进行动态更新。下面的代码中将查询操作和更新操作写在一起了。
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=222222;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int Max[MAXN<<2];
int h,w,n;
void PushUp(int rt){
Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);//根节点记录最大宽度
}
void Build(int l,int r,int rt){
Max[rt]=w;//初始时每个叶子节点的宽度为w,共有h个叶子节点
if(l==r)
return ;
int m=(l+r)>>1;
Build(lson);
Build(rson);
}
int Query(int x,int l,int r,int rt){
if(l==r){//当查询到叶子节点时更新最大宽度
Max[rt]-=x;
return l;//返回此叶子所代表的行号
}
int m=(l+r)>>1;
int ret=(Max[rt<<1]>=x)? Query(x,lson):Query(x,rson);//寻找最大的查询结果
PushUp(rt);//更新线段树
return ret;
}
int main(){
while(cin>>h>>w>>n){
if(h>n) h=n;//此步为了减少线段树的开销
Build(1,h,1);
while(n--){
int x;
cin>>x;
if(Max[1]<x)cout<<-1<<endl;
else
cout<<Query(x,1,h,1)<<endl;
}
}
return 0;
}