http://acm.hdu.edu.cn/showproblem.php?pid=2795
题意:
有一块h*w的墙,往上面贴一些1*wi的海报,要求每张海报要贴在它所能贴的最高的位置,
而且在最高的位置要贴在最左边。输出每一张海报所在的行。h,w<=10e9, n<=100000
思路:
一种很容易想到的思路是这样的,对于每一张海报,我们从最开始的位置开始找一个适合
它的行,并将其贴上,这样的复杂度就是O(n^2),显然会超时。于是我们就想到优化上面
的那个算法,第一个循环是肯定不能有化了,得到每张海报的长度,可以优化的地方是第
二点,我们如何能快速地找到第一个适合它贴的位置呢,我们可以用线段树来优化它,只
需要记录一个区间的最大剩余长度就可以来判断是否能贴该海报。
代码:
#include<stdio.h>
#include<string.h>
#define LL(a) ( (a)<<1 )
#define RR(a) ( (a)<<1|1 )
#define MAX(a, b) (a)>(b)?(a):(b)
int h ,w , n , nn;
const int MAXN = 200010 ;
int max[MAXN<<2] ;
void build(int l ,int r, int idx){
if(l == r){
max[idx] = w ;
return ;
}
int mid = (l + r)>>1 ;
build(l , mid , LL(idx)) ;
build(mid+1, r , RR(idx)) ;
max[idx] = w ;
}
int update(int ll ,int rr , int idx , int len){
int res ;
if(ll == rr){
if(max[idx] >= len)
max[idx] -= len ;
else return -1 ;
return ll ;
}
int mid = (ll + rr)>>1 ;
if( max[ LL(idx) ] >= len ){
res = update(ll, mid , LL(idx) , len ) ;
}
else if( max[ RR(idx) ] >= len ){
res = update(mid+1, rr , RR(idx) , len ) ;
}
else
res = -1 ;
max[idx] = MAX( max[ LL(idx) ] , max[ RR(idx) ] ) ;
return res ;
}
int main(){
int a ;
while(scanf("%d %d %d",&h,&w,&n) == 3){
nn = (h < n ? h : n) ;
build(1,nn,1) ;
for(int i=1;i<=n;i++){
scanf("%d" ,&a);
printf("%d\n",update(1,nn,1,a) );
}
}
return 0 ;
}