hdu2759 Billbord(线段树)

来源:互联网 发布:磁选机选矿的数据分析 编辑:程序博客网 时间:2024/06/05 14:18

题意:给一个长w宽h的板子,每次往上面贴一个长wi宽1的条子(不可旋转),共n个,每次贴的时候都贴在能贴的最上行的最左端,若贴不下就不贴

           给出w,h,wi,n求每个帖子在第几行,若贴不下,输出-1

思路:使用最大值线段树记录每行剩余长度,树叶表示那一行的剩余长度。在每次贴的时候,若wi>根值,则树上所有叶子都比这个帖子小,故挂不下,输出-1。

           若h>n,则说明多的行不需要,h=n即可,(所以说题目上的h<1e9是吓人的)(当时这里手滑写成了h<n结果re了一个晚上

           对于每次查询,使用深搜来找,找叶子后把叶子值改了,返回叶子的位置就是贴的行数了

#include<cstdio>#include<algorithm>#include<iostream>using namespace std;    struct segn    {        int mi;    }segt[200000*4];    void build(int h,int root,int st,int en)    {        if(st==en)        {            segt[root].mi=h;            return;        }        int mid=(st+en)/2;        build(h,root*2+1,st,mid);        build(h,root*2+2,mid+1,en);        segt[root].mi=h;    }    int adjust_elemt(const int addval,int st,int en,int root)    {            if(st==en)            {                segt[root].mi-=addval;                return st;            }        int mid=(st+en)/2,ret;        if(segt[2*root+1].mi>=addval)        ret=adjust_elemt(addval,st,mid,root*2+1);        else        ret=adjust_elemt(addval,mid+1,en,root*2+2);        segt[root].mi=max(segt[root*2+1].mi,segt[root*2+2].mi);        return ret;    }    int main()    {        int h,w,n,yes,cur;        while(~scanf("%d%d%d",&h,&w,&n))        {    if(h>n)h=n;            build(w,0,0,h-1);            for(int i=0;i<n;i++)            {scanf("%d",&cur);                if(cur>segt[0].mi)printf("-1\n");                else{yes=adjust_elemt(cur,0,h-1,0);printf("%d\n",yes+1);}            }        }        return 0;    }


原创粉丝点击