HDU2795 billboard【转化为线段树。】

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

hhanger大神的题目,水题都得有点思维。可怜

 

 

题意:h*w的木板,放进一些1*L的物品,求每次放空间能容纳且最上边的位子
思路:每次找到最大值的位子,然后减去L
线段树功能:query:区间求最大值的位子(直接把update的操作在query里做了)

 

 

技巧挺好,一开始自己思路建个超大二维数组,显然内存不够。

然后。  线段树的话其实就是深搜,if(l==r) 返回的肯定是最左边的结点,哈~

判断的时候直接用Max[1]与p比较就能判断是否输出-1,赞一个!!

#include <iostream>

#include <cstdio>

#include <cmath>

#include <cstring>

#include <algorithm>

using namespace std;



#define lson rt<<1,l,m

#define rson rt<<1|1,m+1,r



int h,w,n;



const int maxn=200005;// 是200000还是20000要搞清楚

int Max[maxn<<2];     //开maxn的多少倍结合最底层的结点数加以注意



void Pushup(int rt)

{

    Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);

}

void build(int rt,int l,int r)

{

    Max[rt]=w;

    if(l==r) return;

    int m=(l+r)>>1;

    build(lson);

    build(rson);

}

int query(int p,int rt,int l,int r)//技巧5 . update放在query里面了

{

    if(l==r)

    {

        Max[rt]-=p;

        return l;// 2. 返回行数

    }



    int m=(l+r)>>1;

    int ret;

    ret=(Max[rt<<1]>=p)?query(p,lson):query(p,rson);// 技巧1.这地方深搜返回最左边的结点即符合的。

    Pushup(rt);// 技巧4 . 自己写这个地方有可能会忘

    return ret;

}



int main()

{

    while(scanf("%d%d%d",&h,&w,&n)!=EOF)

    {

        if(h>n) {h=n;}

        build(1,1,h);



        int p;

        for(int i=1;i<=n;i++)

        {

            scanf("%d",&p);

            if(Max[1]<p) printf("-1\n"); // 技巧3.Max[1]最根结点一定是最大值

            else

            {

                int ans=query(p,1,1,h);

                printf("%d\n",ans);

            }

        }

    }

    return 0;

}


 

 

 

你可能感兴趣的:(HDU)