链接:http://acm.hdu.edu.cn/showproblem.php?pid=2795
题意:有一个h*w的广告牌,往上面按顺序贴1*w[i]的广告,要求尽量靠上靠左,能贴上去输出贴在第几行,否则输出-1
#include<cstdio>
#include<iostream>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 200010;
int mm[maxn<<2];
int h,w,n,a;
void pushup(int rt){
mm[rt] = max(mm[rt<<1],mm[rt<<1|1]);
}
void build(int l,int r,int rt) {
if (l == r){
mm[rt] = w;
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
pushup(rt);
}
int update(int x,int l,int r,int rt){
if (l == r) {
mm[rt] -= x;
return l;
}
int m = (l + r) >> 1;
int ret;
if(mm[rt<<1] >= x) ret = update(x , lson);
else ret = update(x , rson);
pushup(rt);
return ret;
}
int main(){
while(~scanf("%d%d%d",&h,&w,&n)){
if(h>n)h=n;
build(1,h,1);
while(n--){
scanf("%d",&a);
if(a>mm[1])printf("-1\n");
else printf("%d\n",update(a,1,h,1));
}
}
return 0;
}
因为要求尽量靠左上,所以mm数组存的是这个线段上最大的空余部分是多大,然后更新的时候判断左儿子是否大于当前广告的长度,如果可以就继续,否则就搜右儿子
找到后返回l就是第几行,然后把mm[rt]将去相应的长度就可以了~