hdu2795 Billboard (机智的线段树点更新)

来源:互联网 发布:四维星瓷砖软件下载 编辑:程序博客网 时间:2024/05/22 06:57

    题目大意:在一块h层的广告牌上面贴广告,每个广告有一层宽,每个广告尽量往上往左贴。问贴的广告在第几层。

    做法:这道题很机智的可以用线段树,把 1~h 层看作 线段 1~h ,树上每个节点记录线段的剩余长度最大值。贴广告时,若广告长度>左儿子节点,则进入做子树,否则看右儿子是否符合要求,若符合,则进入右子树。

    以下是代码:

#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>using namespace std;int maxx[1000000];int ans;void pushup(int o){    maxx[o]=max(maxx[o*2],maxx[o*2+1]);}void build(int o,int L,int R,int w){    int ls=o*2,rs=o*2+1,m=L+(R-L)/2;    if(L==R){        maxx[o]=w;        return ;    }    build(ls,L,m,w);    build(rs,m+1,R,w);    pushup(o);}void update(int o,int L,int R,int wi){    int ls=o*2,rs=o*2+1,m=L+(R-L)/2;    if(L==R){        maxx[o]-=wi;        ans=L;        return ;    }    if(maxx[ls]>=wi)        update(ls,L,m,wi);    else if(maxx[rs]>=wi)        update(rs,m+1,R,wi);    pushup(o);}int main(){    //freopen("in.txt","r",stdin);    int h,w,n;    while(scanf("%d%d%d",&h,&w,&n)!=EOF){        memset(maxx,0,sizeof(maxx));        if(h>200000)h=200000;    //这里很重要。。不然数组会爆炸RE        build(1,1,h,w);        while(n--){            ans=-1;            int x;            scanf("%d",&x);            update(1,1,h,x);            printf("%d\n",ans);        }    }    return 0;}


0 0
原创粉丝点击