NOI2007 貨幣兌換 題解

2022-08-11 18:03:15 字數 1575 閱讀 9255

​ 初始時有\(m\)的本金,已經知道之後\(n\)天內每一天\(a\)券與\(b\)券的價值,每一天可以**或賣出金券。

​ 賣出金券方法如下:自己提供乙個\([0,100]\)內的實數\(op\),意義為將\(op\%\)的\(a\)券和\(op\%\)的\(b\)券賣出。

​ **金券方法如下:每一天給定乙個\(r\),自己給出乙個**的金額\(ip\),滿足**\(a\)券與\(b\)券數量之比為\(r\),總價值為\(op\)。

​ 求\(n\)天後擁有的最大總價值。

​ 首先不難想到乙個這樣的策略,賣出金券時,一定全部賣出是最優的,這個感覺比較顯然,有了這個,\(op\)的限制就不存在了。

​ 考慮dp,我們可以得到乙個這樣的轉移方程:

​ \(dp_i=\max(dp_,\max\limits_^\)\),其中\(x_i=\frac,y_i=\frac\)。

​ 表示第\(i\)天不操作,或者把第\(j\)天**的金券全部賣出的最大價值。這是乙個\(o(n^2)\)的演算法,能拿到60pts。

​ 考慮如何去優化,看見式子中含與\(i,j\)有關部分之積\(a_i \times dp_j\),發現這是乙個典型的斜率優化。

​ 忽略掉\(\max\)符號,改寫一下式子:\(y_j=-\fracx_j+\frac\),斜率已知,目標是最大化截距,可以維護乙個上凸殼。

​ 但是,我們發現每一次加入的點\((x_i,y_i)\)無論在橫座標上還是縱座標上都不單調,無法簡單的用單調佇列維護,於是考慮用平衡樹動態維護凸殼,來實現在任意位置插入及刪除,總複雜度\(o(nlogn)\)。

#include#define eps 1e-8

#define db double

using namespace std;

int n,m;

db dp[100005];

db a[100005],b[100005],r[100005],x[100005],y[100005];

struct splay

inline db slope(int a,int b)

}

return;

}int findpre(int x)

else

now=son[now][0];

}return ans;

} int findsuf(int x)

else

now=son[now][1];

}return ans;

}void add(int x)

else

lk[x]=+dbl_max;

if(son[x][1])

else

rk[x]=-dbl_max;

if(lk[x]+eps<=rk[x])

return;

}int find(db k)

return 0;

} }t;int main()

dp[0]=m;

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

printf("%0.3lf\n",dp[n]);

return 0;

}

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...