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