題解 乾草堆

2021-10-25 15:49:14 字數 2141 閱讀 5375

t4實在做不動,就來頹一篇題解

就是把乙個數列分成若干段,使得這些段的和從前往後不上公升,在滿足這個要求的情況下段數最多

考場上當開始想了乙個貪心的思路,就是正著遍歷,當這個階段高度是最優的時候,下乙個階段就直接順承這個階段的寬度

但是很容易就會hack:

431

33

上面這個資料,i=2

i=2i=

2 時高度最優為 1

11 ,但是後面就放不下了,相反,如果在 i=2

i=2i=

2 時只放一層,此時寬度為 4

44,這樣後兩個都能放

雖然這是錯的,但是乙個很巧的思路就是倒著:

把乙個數列分成若干段,使得這些段的和從前往後不上公升

換句話說,就是:把乙個數列分成若干段,使得這些段的和從後往前不下降,就是做乙個倒金字塔

這樣,我們就會發現這個貪心思路是可行的,因為當我們已經可以加一層的時候:

而顯然的是,最外層寬度越大,一定不會劣與最外層寬度越小

所以,無論如何,可以加一層的時候,加一層比不加更優

那麼我們就可以打出乙個暴力的**:

#include

#include

#include

using

namespace std;

const

int maxn=

1e5+5;

int a[maxn]

;int sum[maxn]

;int f[maxn]

;int g[maxn]

;int

main()

for(

int i=

1;i<=n;i++

)memset

(g,0x3f

,sizeof

(g))

; g[n+1]

=0;for

(int i=n;i>=

1;i--)}

}}printf

("%d"

,f[1])

;}

但是這個**時間複雜度為 o(n

2)

o(n^2)

o(n2

),無法通過這道題

可以發現,我們就是要找乙個編號最小的點j

jj,滿足sum

[j−1

]−su

m[i−

1]

>=g

[j

]sum[j−1]−sum[i−1]>=g[j]

sum[j−

1]−s

um[i

−1]>=g

[j]。這個可以單調佇列維護g[j

]−su

m[j−

1]

g[j]−sum[j−1]

g[j]−s

um[j

−1]的min

\mathrm

min最終code

#include

#include

#include

using

namespace std;

const

int maxn=

1e5+5;

int a[maxn]

;int sum[maxn]

;int g[maxn]

;int f[maxn]

;int q[maxn]

;int

main()

for(

int i=

1;i<=n;i++

)int head=

1,tail=1;

q[1]=n+1;

for(

int i=n;i>

0;i--

) g[i]

=sum[q[head]-1

]-sum[i-1]

; f[i]

=f[q[head]]+

1;while

(head-sum[i-1]

]-sum[q[tail]-1

])q[

++tail]

=i;}

printf

("%d"

,f[1])

;}

0x50 動態規劃(練習)20 乾草堆(題解)

題目鏈結 題意 奶牛們討厭黑暗。為了調整牛棚頂的電燈的亮度,bessie必須建一座乾草堆使得她能夠爬上去夠到燈泡。一共有n大包的乾草 從1到n編號 依靠傳送帶連續的傳輸進牛棚來。第i包乾草有乙個寬度wi。所有的幹草包的厚度和高度都為1。bessie必須利用所有n包乾草來建立起乾草堆。她可以想放多少包...