题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2795
题意:有一块h*w 的广告版,有n块1*w[i]的广告,就着放广告尽量在顶上,尽量先放左边的原则,问在第几行能把广告放下,如果放不下,就打印-1;
思路:我们可以根据每一行建树,每一个子叶表示每一行的容量,而节点存放子节点的最大值,然后从最顶到底,快速查找能存放下广告的一行。
总之还是简单的线段树问题,难点在于抽象模型。
#include <iostream> #include <cstdio> #define MID (l + r) >> 1 #define LS rt << 1 #define RS rt << 1 | 1 #define LSON l,m,rt << 1 #define RSON m + 1,r,rt << 1 | 1 #define MAX 999999 using namespace std; int imax[MAX << 2]; inline void pushup(int rt) { imax[rt] = max(imax[LS],imax[RS]); } void build(int w,int l,int r,int rt) { if(l == r) { imax[rt] = w; return ; } int m = MID; build(w,LSON); build(w,RSON); pushup(rt); } int query(int x,int l,int r,int rt) { if(l == r) { imax[rt] -= x; return l; } int m = MID; int ret = (imax[LS] >= x) ? query(x,LSON) : query(x,RSON); pushup(rt); return ret; } int main() { int h,w,n; while(~scanf("%d%d%d",&h,&w,&n)) { //优化:如果空间远远更能够h>n,那么就让h=n(一行一条广告) if(h > n) h = n; build(w,1,h,1); while(n--) { int x; scanf("%d",&x); if(imax[1] < x) //如果最顶端没有位置 puts("-1"); else printf("%d\n",query(x,1,h,1)); } } return 0; }
时间: 2024-10-17 10:20:05