题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2795
分析:
题目大意是给一个h*w的公告牌,h是高度,w是宽度,一个单位高度1为一行,然后会有一些公告贴上去,公告是1*wi大小的长纸条,优先贴在最上面并且最左边的位置,如果没有空间贴得下,就输出-1,可以的话,就输出所贴的位置(第几行)。
叶节点[x,x]表示board的第x行还可以放置的长度,区间[a,b]表示第a行到b行中剩下空间最大的那一行是多少,如果要把长w的公告放入 board时就是update,优先往左子树走(如果左子树的空间足够的话),一直走到叶节点,更新这个叶节点剩下的长度,然后再向上更新。
#include <iostream> #include <cstdio> using namespace std; const int maxn = 200010; int w; struct Node { int l,r,mid; int max; }d[maxn*3]; void build(int L,int R,int rt) { d[rt].l = L; d[rt].r = R; d[rt].mid = (L+R)/2; d[rt].max = w; if (L==R) return; build(L,(L+R)/2,rt*2); build((L+R)/2+1,R,rt*2+1); } int update(int board,int rt) { if (d[rt].l == d[rt].r) { d[rt].max -= board; return d[rt].l; } int ret; if (d[rt*2].max >= board) ret = update(board,rt*2); else ret = update(board,rt*2+1); d[rt].max = max(d[rt*2].max,d[rt*2+1].max); return ret; } int main() { int h,n,board; while (scanf("%d%d%d",&h,&w,&n)==3) { build(1,min(h,n),1); while(n--) { scanf("%d",&board); if (d[1].max < board) printf("-1\n"); else printf("%d\n",update(board,1)); } } return 0; }