目錄好像是二刷了吧,但是肯定不止見過兩次了。
傳送門 to luogu
不難發現 題目提示也給了 必定存在一種最優方案滿足**時用完所有錢,賣出時賣完所有**。
先分析清楚題,假如說在第 \(i\) 天用 \(s\) 元買**,那麼最後
\[\text_b=_i+b_i} \\
\text_a=\text_b\text_i=_i\over a_i\text_i+b_i}
\]那麼我們定義 \(f_i\) 表示第 \(i\) 天能夠得到的最多的錢,那麼就有乙個 \(\mathcal o(n^2)\) 的轉移:
\[f_i=\max_^\_j\over a_j\text_j+b_j}+b_i\times _j+b_j}\}
\]最後還要 \(f_i=\max\\}\) 表示今天什麼都沒乾,初始狀態 \(f_0=s\).
十分容易地拿下 \(60pts\),考慮優化這個 \(\mathcal o(n^2)\) 的 \(\tt dp\).
定義 \(t_i=a_i\text_i+b_i\),那麼轉移寫作
\[f_i=\max_^\_j\over t_j}+b_i\times \}
\]發現這兩個分數都只和 \(j\) 有關,那麼這個式子就是可以斜率優化的。
記 \(x_j=_j\over t_j},y_j=\),我們將這個方程改寫一下:
\[f_i=a_ix_j+b_iy_j \\
\rightarrow y_j=-x_j+
\]從含義上講,即對於之前的所有決策點,在平面上記其為 \(\lang x_j,y_j\rang\),然後用 \(-\) 的直線去任意切乙個,得到的最大截距就是 \(f_i\over b_i\),然後就可以算出最大 \(f_i\) 了。
但是有乙個問題,那就是這個 \(x_j\) 並不是單調的,所以我們還不能使用單調佇列對其進行維護,但是我們可以使用 \(\tt cdq\) 分治,每次把左邊的 \(x_i\) 進行排序,考慮左邊對右邊的貢獻,維護乙個不動凸包,然後在凸包上面二分即可,這樣做複雜度 \(\mathcal o(n\log^2 n)\). 其實也不需要再凸包上進行二分,只需要將右邊按照斜率 \(k=-\) 排序,每次在凸包前面檢視是否有更優解,有就將隊頭彈出,直到找到最優解更新答案即可。
#include#includeusing namespace std;
typedef long long ll;
templateinline t fab(const t x)
templateinline t readin(t x)
inline int operator ==(const double rhs) const
inline double operator -(const double rhs) const
inline double operator +(const double rhs) const
inline double operator *(const double rhs) const
inline double operator /(const double rhs) const
inline double operator -() const
} doub;
int n;
doub a[maxn+5], b[maxn+5], rate[maxn+5];
doub x[maxn+5], y[maxn+5], f[maxn+5];
inline void input()
}inline int comp(const doub a,const doub b)
inline int cmpx(const int i, const int j)
inline doub slope(const int i, const int j)
inline doub slope(const int i)
int q[maxn+5], op, ed;
int id[maxn+5];
void solve(const int l, const int r)
int mid=(l+r)>>1;
solve(l, mid);
for(int i=l; i<=r; ++i) id[i]=i;
sort(id+l, id+mid+1, cmpx);
sort(id+mid+1, id+r+1, cmpslope);
op=1, ed=0;
for(int i=l; i<=mid; ++i)
for(int i=mid+1; i<=r; ++i)
solve(mid+1, r);
}signed main()
有些地方精度太高了,調了好久......卡進度真的沒意思。
有時候斜率並不能保證一些東西是單調的,這個時候你就需要使用動態凸包或者用 \(\tt cdq\) 處理這種座標不保證單調的情況。
另外,對於 \(\tt dp\) 方程的變形,要將和 \(i\) 有關的,和 \(j\) 有關的變數進行剝離,這樣才能更好地處理。
NOI2007 貨幣兌換
今天聽了crazy和samjia的noi雜 砸 題選講,感覺自己萌萌噠 於是就來怡情地寫了這道題。額 o 這個不好說啊。語文不好不好裱我 還是貼圖吧。咳咳,希望大家都看懂題了。乙個很明顯的貪心思路就是,我們每天要不全買,要不全賣。因為一有利益我們就去佔,一有虧損我們就不碰。那麼我們可以有dp方程 f...
Noi2007 貨幣兌換
傳送門 小半個上午 一下午都給了這題了qaq 都知道是斜率優化,問題是我看這題根本就是乙個人乙個式子啊 算了,把我的過程列出來吧 令 f i 表示第i天結束時強制賣出所有金券最多能得到的軟妹幣數量,列舉上一次 金券的時間,就有 beginf i max end 這裡沒有寫隱含條件 f i ge f ...
NOI2007 貨幣兌換
題目 先來畫一畫柿子 設 dp i 表示你第 i 天之後最多剩下多少錢 考慮一下對於 i 的轉移,我們肯定要在之前列舉一天 j 這一天把所有的東西買進來,之後在 i 天賣掉 設那天買進 a 的量為 d a 買進 b 的量為 d b 我們可以得到這樣的方程 d ap a d bp b dp j d a...