Billboard----HDU_2795----线段树之单点更新

来源:互联网 发布:李兴华讲的java怎么样 编辑:程序博客网 时间:2024/05/17 18:24

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2795

/*Author:Bob Lee2012.9.24================================================这题还是有必要写一下首先是题意给你一个h*w的方盒子然后给你若干个1*wi的通知每次你都要往里面放从top往下放top为1如果能往最前面放就尽量往前面放放不下就往下面放现在要你一个一个的放,问你每次放在第几行如果放不下,就-1这题如果不看胡浩大神的博客,我真的还一时想不到要用线段树建立一颗线段树MAX[i]表示由i到下面的h的中最大的可放空间然后将这所有的都更新到子树的根节点这样就可以将效率大大的提高还有一个小技巧因为这里的h太大了但是我们可以发现每个小物体的h均为1所以我们可以以n来建立线段树所以这样就可以把这棵树建立起来了。*/#include<iostream>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define maxn 200005int MAX[maxn<<2];int h,w,n;void PushUP(int rt){    MAX[rt] = MAX[rt<<1]>MAX[rt<<1|1] ? MAX[rt<<1] : MAX[rt<<1|1];}void build(int l,int r,int rt){    /*    这里就和以往不同    将区间内的最大值保存到rt里面    那么初始值就应该是w    因为我一个都没放    */    MAX[rt] = w;    if(l == r)        return;    int m = (l+r)>>1;    build(lson);    build(rson);}/*这个函数也要拿出来说一下如果找到了可以放的最大的,那么就返回如果我的左儿子下面的最大的都放不下那就去右边找当然先前是判断了一定可以找到的那就是要和MAX[1]比较也就是说在query的时候把update的工作也做了*/int query(int x,int l,int r,int rt){    if(l==r)    {        MAX[rt] -= x;        return l;    }    int m = (l+r)>>1;    int ret = (MAX[rt<<1] >= x) ? query(x,lson):query(x,rson);    PushUP(rt);    return ret;}int main(){    while(~scanf("%d%d%d",&h,&w,&n))    {        if(h>n)            h=n;        build(1,h,1);        while(n--)        {            int x;            scanf("%d",&x);            if(MAX[1] < x)                puts("-1");            else                printf("%d\n",query(x,1,h,1));        }    }    return 0;}


 

原创粉丝点击