题目意思很简单,给一个面积为h*w的板子,每次选择一个最上且最左的区域贴上一张纸1*wi,求每次贴的行。每次找出行中保留面积能够满足纸的面积的即可。如果直接用数组模拟的话,肯定会超时。这个题目可以用线段树做。看题的时候,发现h比较大,开数组肯定会超内存。分析一下,发现有n次插入,我们可以假设每次都只能在新的一行中插入,在极限数据下,也只需要4*200000的空间,这样肯定不会超内存。结构体中保存一个最大值,也是每个区间的剩余面积。在每次查询的时候,由于要更新每行的数据,所以要在回调更新最大值。代码如下:
/*
ID : csuchenan
PROG: Billbord hdoj 1795
LANG: C++
*/
#include<stdio.h>
#define MAXN 300010
struct Node{
int l ;
int r ;
int nmax ;
}node[MAXN * 4] ;
int h ;
int w ;
int n ;
bool init() ;
void work() ;
void build(int l , int r , int c) ;
int query(int val , int c) ;
int main(int argc , char *argv[]){
while(init()){
work() ;
}
return 0 ;
}
bool init(){
if(scanf("%d %d %d" , &h , &w , &n)!=3){
return 0 ;
}
if(h > n)
h = n ;
build(1 , h , 1) ;
return 1 ;
}
void work(){
int val ;
int res ;
while(n--){
scanf("%d" , &val) ;
res = query(val , 1) ;
printf("%d\n" , res) ;
}
}
void build(int l , int r , int c){
node[c].l = l ;
node[c].r = r ;
node[c].nmax = w ;
if(l == r)
return ;
int mid = (l+r)>>1 ;
build(l , mid , c<<1) ;
build(mid + 1 , r , c<<1|1) ;
return ;
}
int query(int val , int c){
if(node[c].nmax < val){
return -1 ;
}
if(node[c].l==node[c].r){
node[c].nmax -= val ;
return node[c].l ;
}
int result ;
if(node[c<<1].nmax >= val)
result = query(val , c<<1) ;
else
result = query(val , c<<1|1) ;
node[c].nmax = (node[c<<1].nmax) > (node[c<<1|1].nmax) ? (node[c<<1].nmax) : (node[c<<1|1].nmax) ;
return result ;
}