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包乾草來建立起乾草堆。她可以想放多少包...