hdu2759 Billbord(線段樹)

題意:給一個長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;
    }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章