HNOI2008 玩具裝箱TOY

2022-03-19 20:28:11 字數 1540 閱讀 8934

[hnoi2008]玩具裝箱toy

"這是一道經典的斜率優化入門題,就用這題來作個總結好了."

這道題用到的是單調佇列(我只會這玩意兒)的斜率優化.

我們整理一下題意會發現它的狀態轉移方程就是下面這東西:

\[dp[i]=min(dp[j]+(sum[i]+i-sum[j]-j-l-1)^2),i>j

\]上面這張圖講得已經很清楚了.

我們如果把含\(j\)的相關變數都看成點的座標的話,此時我們要做的就是盡量讓截距更小.

怎麼讓截距最小呢?難道乙個乙個比較嗎?

我們再來看下面這張圖:

上面三個點是我們可供選擇的三個點,這條直線就是我們就是要使這條一直斜率的截距最小.

高中數學學線性規劃的時候我們都知道,顯然是選途中的\(b\)點.

那麼對於這一條直線,我們根據斜率和座標可以計算截距,從而得到dp值.

那剩下兩個點呢?

對於\(a\)點,我們是不是可以丟掉它了?是的,由於我們的斜率是不斷增大的,\(a\)點是不可能用來轉移後面的狀態了,所以把它剔除.

還有\(c\)點,當斜率到達一定大小,例如下圖:

此時我們就要用到\(c\),而\(b\)又可以剔除.

於是我們只要維護乙個凸包,而且這個凸包相鄰兩個點連的斜率要大於當前這條線的斜率.就像剛剛這個例子一樣.一旦最左端的乙個點和次左端的點的連線要小於當前的斜率了,就把最左端的點剔除.

這樣每次遇到新的直線,直接拿最左端的點(隊頭)來轉移,加入乙個新點就加到最右邊(隊尾),因為橫座標也是遞增的.再加入這個點之前,我們一定要保證下凸的性質,例如下面這個例子:

\(b\)顯然要被剔除.

為什麼一定維護凸包呢?為什麼一定是彈掉\(b\).\(c\)為什麼更優呢?自己想象一下,一條直線斜率大於\(cg\)的直線從下面平移上來,走啊走,最後一定會在\(c\)這裡停下.如果是一條斜率小於\(gc\)大於\(gf\)的,顯然會在\(g\)停下,這樣\(b\)就沒有人和用武之地了.

在這裡我們總結一下,單調佇列斜率優化的步驟:

1.彈隊頭,就是最左邊的點.

2.放直線,算答案,得到當前狀態的答案,得到新的待加入的點.

3.彈隊尾,把插入新點之後不合法的點彈掉.最後加入新點就好了.

**:

#include#include#include#define maxn 50005

#define ll long long

using namespace std;

int q[maxn];

double a[maxn],b[maxn],dp[maxn],sum[maxn];

double x(int x)

double y(int x)

double slope(int a,int b)

int main()

b[0]=l+1;//b[0]=sum[0]+0+l+1=l+1

int tail=1,head=1;

for(int i=1;i<=n;i++)

printf("%lld",(ll)dp[n]);

return 0;

}

HNOI2008 玩具裝箱toy

重點在講斜率優化 description p教授要去看奧運,但是他捨不下他的玩具,於是他決定把所有的玩具運到北京。他使用自己的壓縮器進行壓縮,其可以將任意物品變成一堆,再放到一種特殊的一維容器中。p教授有編號為1.n的n件玩具,第i件玩具經過壓縮後變成一維長度為ci.為了方便整理,p教授要求在乙個一...

HNOI2008 玩具裝箱toy

dp i min dp j sum i sum j c 2 dp k sum i sum k c 2 dp k si sum k 2 dp k si 2 2 si sum k sum k 2 dp k sum k 2 dp j sum j 2 2 si sum k sum j yk yj 2 si ...

HNOI2008 玩具裝箱TOY

題目描述 p教授要去看奧運,但是他捨不下他的玩具,於是他決定把所有的玩具運到北京。他使用自己的壓縮器進行壓縮,其可以將任意物品變成一堆,再放到一種特殊的一維容器中。p教授有編號為1 n的n件玩具,第i件玩具經過壓縮後變成一維長度為ci.為了方便整理,p教授要求在乙個一維容器中的玩具編號是連續的。同時...