HDU2795 Billboard 线段树单点更新变形

题目链接:点击打开链接


题目大意:有一个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;
}


你可能感兴趣的:(HDU2795 Billboard 线段树单点更新变形)