hdu 2795 Billboard

来源:互联网 发布:大数据性能 编辑:程序博客网 时间:2024/04/30 09:54

题意:给一个h*w的公告牌,h是高度,w是宽度,一个单位高度1为一行,然后会有一些公告贴上去,公告是1*wi大小的长纸条,优先贴在最上面并且最左边的位置,如果没有空间贴得下,就输出-1,可以的话,就输出所贴的位置(第几行)。

思路:建线段树时取的n,我们只需要行的数量,这个10^9很是吓人,只需要取 min(h,n)即可,因为h太多也是无用的,总共才n个广告吗,多的行建出来只是浪费空间。然后结点的val值表示node[u].l到node[u[.r这个区间能容纳的最大宽度,叶子结点就是代表其所对应的行的剩余宽度。每次query时,先看左边的能否满足,然后看右边的。

如果理清了思路就很简单了,但是本人不知道为啥,我用自己宏定义的max 和min就超时,用系统的就直接AC。

 

#include<cstdio>#include<cstring>#include<iostream>#define L(u) (u<<1)#define R(u) (u<<1|1)using namespace std;const int N = 200001;int h,w,n,tot;struct Node {int l,r,val;};Node node[N*3];void pushUp(int u){    node[u].val = max(node[L(u)].val , node[R(u)].val);}void build(int u,int left,int right){    node[u].l = left,node[u].r = right;    node[u].val = w;    if(node[u].l==node[u].r)    {        return;    }    int mid = (node[u].l+node[u].r)>>1;    build(L(u),left,mid);    build(R(u),mid+1,right);}void upDate(int u,int r,int x)//3个参数分别表示现在更新的结点,r表示需要更新的行,x表示需要更新的数值{   if(node[u].l==node[u].r&&node[u].l==r)   {    node[u].val -= x;    return;   }   int mid = (node[u].l+node[u].r)>>1;   if(r<=mid)    {      upDate(L(u),r,x);    }    else    {      upDate(R(u),r,x);    }    pushUp(u);}int query(int u,int x){    if(node[u].val<x)        return -1;    if(node[u].l==node[u].r&&node[u].val>=x)        return node[u].l;    else    {        if(node[L(u)].val<x)        {           if(node[R(u)].val<x)           {             return -1;           }           else           {               return query(R(u),x);           }        }        else        {           return query(L(u),x);        }    }}int main(void){    while(scanf("%d %d %d",&h,&w,&n)!=EOF)    {        tot = min(h,n);        build(1,1,tot);        for(int i=1;i<=n;++i)        {            int a;            scanf("%d",&a);            int x = query(1,a);            if(x==-1)             printf("%d\n",x);            else            {                printf("%d\n",x);                upDate(1,x,a);            }        }    }    return 0;}


原创粉丝点击