【問題描述】
小 y最近在一家金券交易所工作。該金券交易所只發行交易兩種金券:a紀念券(以下簡稱a券)和b紀念券(以下簡稱b券)。每個持有金券的顧客都有乙個自己的 帳戶。金券的數目可以是乙個實數。每天隨著市場的起伏波動,兩種金券都有自己當時的價值,即每一單位金券當天可以兌換的人民幣數目。我們記錄第k天中a券 和b券的價值分別為ak和bk(元/單位金券)。
為了方便顧客,金券交易所提供了一種非常方便的交易方式:比例交易法。
比例交易法分為兩個方面:
a)賣出金券:顧客提供乙個[0,100]內的實數op作為賣出比例,其意義為:將op%的a券和op%的b券以當時的價值兌換為人民幣;
b)**金券:顧客支付ip元人民幣,交易所將會兌換給使用者總價值為ip的金券,並且,滿足提供給顧客的a券和b券的比例在第k天恰好為ratek;
例如,假定接下來3天內的ak、bk、ratek的變化分別為:
時間ak
bkratek
第一天111
第二天122
第三天223
假定在第一天時,使用者手中有100元人民幣但是沒有任何金券。
使用者可以執行以下的操作:
時間使用者操作
人民幣(元)
a券的數量
b券的數量開戶無
1000
0第一天
**100元050
50第二天
賣出50%
7525
25第二天
**60元
1555
40第三天
賣出100%
2050
0注意到,同一天內可以進行多次操作。
小y是乙個很有經濟頭腦的員工,通過較長時間的運作和**測算,他已經知道了未來n天內的a券和b券的價值以及rate。他還希望能夠計算出來,如果開始時擁有s元錢,那麼n天後最多能夠獲得多少元錢。
【輸入格式】
第一行兩個正整數n、s,分別表示小y能預知的天數以及初始時擁有的錢數。接下來n行,第k行三個實數ak、bk、ratek,意義如題目中所述。
【輸出格式】
只有乙個實數maxprofit,表示第n天的操作結束時能夠獲得的最大的金錢數目。答案保留3位小數。
正解=動歸+平衡樹
考慮簡單dp
狀態:設f[i]為第i天能賺的最多錢為多少
方程:f[i]=max(f[i-1],na*a+nb*b)(j< i)
(na,nb為第j天能換到的a劵數量和b劵數量)
考慮優化:
設 na 為 x,nb 為 y
則sum=x*a+y*b 既 y = -a/b*x+sum/b
由於a,b為定值
sum的max以 -a/b 為斜率的過點(x,y)的截距的max*b
顯然可能得到max解截距的點必然是個上凸殼
建立以x為關鍵字的平衡樹維護值(其實很簡(dan)單(teng))
由於在樹上的點對映的截距具有單調性,
找最大值是便可通過平衡樹的前驅後繼判斷max在左子樹或右子樹;
**如下:
1 #include2 #include3 #include4 #includeview code5 #include6 #include7
#define inf 99999999
8#define ll long long
9#define cint(o) const int o=0
10#define cdou(o) const double o=0
11#define min(num1,num2) if(num1>num2) num1=num2
12#define max(num1,num2) if(num113
struct
tree
18 }a[100010
];19
introot,total,n;
20const
long
double o=1e-8;21
void cal(double sum,double a,double b,double k,double &na,double &nb)
25void rig(int
now)
3536
void lef(int
now)
46double
cross(tree a,tree b,tree c)
50void splay(int now,int f=0)64
if(!f) root=now;65}
6667
void
creat()
75int prev(int
now)
81int succ(int
now)
87void del(int start,int now,int
end)
93void maintain(int
now)
100while(1
)109
while(1
)118
}119
void insert(double x,double
y)126
if(a[now].x-x>o)
127if
(a[now].l)
128 now=a[now].l;
129else
137else
138if
(a[now].r)
139 now=a[now].r;
140else
149}
150}
151double fo(tree now,double
k)154
int pre(int
now)
160161
int suc(int
now)
167double slove(double
k)173
if(now==2
)177
178if
(a[now].l)
184}
185if
(a[now].r)
191}
192return
fo(a[now],k);
193194
}195
} 196
intmain()
210 printf("
%.3lf
",s);
211 }
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...