HDU2795 贴广告

来源:互联网 发布:网络发展新技术 编辑:程序博客网 时间:2024/05/17 07:44

HDU2795 Billboard
题意:有一块h*w的广告牌,往上面贴n个1*wi的广告(不可覆盖),尽量贴最上面,满足最上面时尽量贴最左边,如果哪个广告贴不下不能就输出-1,贴的下就输出它在哪一行
思路:如果以行数为区间,建立线段树,广告最多有n=200000条,即使每个广告一行也就需要h=200000行就足够了;树的叶子节点表示广告牌的高度,而父节点存储子节点的最大剩余值;所以每次找到最大值的位置(位于叶子节点)然后减去wi

#include<cstdio>#include<algorithm>using namespace std;struct node{    int left,right;    int len;}tree[200001*4];//广告即使每个占一行,最多也就200000行,所以h最大200000就够了int w,v;//广告牌的宽及广告的宽void Build(int l,int r,int cur){    tree[cur].left=l;    tree[cur].right=r;    tree[cur].len=w;//叶子节点放入牌子的宽度,其他节点放入左右儿子节点的最                    //大值,刚开始叶子都一样所以最大值也就是广告牌的宽度    if(l==r)return ;    int mid=(l+r)/2;    Build(l,mid,cur*2);    Build(mid+1,r,cur*2+1);}int Query(int cur){//查询和更新结合在一起    if(tree[cur].left==tree[cur].right){        tree[cur].len-=v;//贴成功        return tree[cur].left;//返回所在的行    }    int ret;    if(tree[cur*2].len>=v)ret=Query(cur*2);//一旦左儿子的len>=v则往左儿子找    else ret=Query(cur*2+1);//左儿子不行才找右儿子,这样保证了topmost    tree[cur].len=max(tree[cur*2].len,tree[cur*2+1].len);//先更新父节点的len值    return ret;//后返回到上一层}int main(){    int h,n;//广告牌的高及广告个数    while(scanf("%d%d%d",&h,&w,&n)!=EOF){        if(h>n)h=n;//广告即使每个占一行,最多也就n行,所以当h>n时取n即可        Build(1,h,1);        while(n--){            scanf("%d",&v);//广告的宽            if(tree[1].len<v)printf("-1\n");//根节点存的是所有叶子节点存的最大值            else printf("%d\n",Query(1));        }    }    return 0;}
0 0
原创粉丝点击