题目链接:点击打开链接
题目大意:有一个h×w的广告牌和n条1×wi的通知,每条通知总是尽可能的往上,在每一层中尽可能往左贴在广告牌上,找出每条通知在广告牌上我位置高度,如果不能贴在广告牌上,位置高度为-1.
分析:要想把通知插到广告牌上,我们需要知道当前位置高度的剩余容量,可以用一个数组num[ i ]来纪录第i层上剩余的最大长度,然后与输入进来的通知的长度x比较。若通知长度大于当前剩余长度,那么就找下一层。我们可以用线段树最底层的单个节点(即tree[ i ].left==tree[ i ].right时)来表示高度,这个区间(节点)存储当前高度的剩余容量。
实现代码如下:
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; #define maxn 200005 int num[maxn<<2]; int h,w,n; void build(int l,int r,int root) { num[root]=w; if(l==r) return ; int m=(l+r)>>1; build(l,m,root<<1); build(m+1,r,root<<1|1); } int query(int x,int l,int r,int root) { if(l==r) { num[root]-=x; return l; } int m=(l+r)>>1; int res=(num[root<<1]>=x)?query(x,l,m,root<<1):query(x,m+1,r,root<<1|1); num[root]=max(num[root<<1],num[root<<1|1]); return res; } int main() { while(scanf("%d%d%d",&h,&w,&n)!=-1) { if(h>n) h=n; build(1,h,1); while(n--) { int x; scanf("%d",&x); if(num[1]<x) printf("-1\n"); else printf("%d\n",query(x,1,h,1)); } } return 0; }