hdu2795 线段树 求区间特殊值

又一个线段树,和前几个有点不太一样,这里的域值保存的是一个区间,或者说是一个长度,即能用的剩余空间。求的也不一样,求的是一个最靠近区间最端点符合条件的值。

  
    
struct node{
int l, r, sl, maxSize;
}st[NN
* 8 ];

sl保存的是那一排的首位置,maxSize表示当前区间的能用最大空间值。这题有四个学习的地方:

key1:当找到叶子节点,且有足够大的空间贴广告时,改变域值,返回。
key2:如果当前区间的最大可用空间都不够用时,即可return。
key3:如果已经找到合适的位置了,右半区间就不用再找了。
key4:每次回溯的时候,要把改变过的最大空间值maxSize,层层返回,层层更新。

 

代码
   
     
#include < stdio.h >
#include
< string .h >
#include
< stdlib.h >
#define NN 200000

struct node{
int l, r, sl, maxSize;
}st[NN
* 8 ];
int h, w, n, row;

int Max( int a, int b){
return a > b ? a : b;
}

void Init( int l, int r, int id){
st[id].l
= l;
st[id].r
= r;
st[id].sl
= 1 ;
st[id].maxSize
= w;

if (r - l <= 1 ){
return ;
}

int mid = (l + r) >> 1 ;

Init(l, mid, id
* 2 );
Init(mid, r, id
* 2 + 1 );
}

void Update( int key, int id){
// key1
if (st[id].r - st[id].l <= 1 && st[id].maxSize >= key){
row
= st[id].r;
st[id].sl
+= key;
st[id].maxSize
-= key;
return ;
}
// key2
if (st[id].maxSize < key){
return ;
}
int mid = (st[id].l + st[id].r) >> 1 ;

Update(key, id
* 2 );
// key3
if (row == - 1 ){
Update(key, id
* 2 + 1 );
}

// key4
st[id].maxSize = Max(st[id * 2 ].maxSize, st[id * 2 + 1 ].maxSize);
}
int main()
{
int i, min;
while (scanf( " %d%d%d " , & h, & w, & n) != EOF){
if (h > n){
h
= n;
}
Init(
0 , h, 1 );
for (i = 1 ; i <= n; i ++ ){
scanf(
" %d " , & w);
row
= - 1 ;
Update(w,
1 );
printf(
" %d\n " , row);
}
}
return 0 ;
}

 

你可能感兴趣的:(HDU)