BZOJ 1492 貨幣兌換Cash

2021-09-07 23:10:50 字數 1955 閱讀 2330

題意:有ab兩種金券,n天,第一天某人有s的錢。給出每天的三個值ai,bi,ratei。每天可以進行的操作有兩種:(1)賣掉x%(0<=x<=100):意味著分別將a種金券和b種金券分別賣掉x%,**分別為ai,bi;(2)買進x元的金券:分別以ai、bi的**買進兩種金券買進的數量比為ratei。一天內可以進行多次操作。求n天後最大的獲利。

思路:(1)首先,得到乙個dp的方程,f[i]表示i天後的最大獲利(最大獲利必然是把所有金券全部賣了),則f[i]=max(f[i-1],ai*yi+bi*xi),xi和yi表示第i天可以有的金券數量,對於xi和yi的計算,我們可以列舉1<=j<=i-1,將f[j]的錢全部全部買成金券,儲存到第i天。想想,有沒有可能這樣:把第j天的錢用一部分買金券,剩下一些錢,然後將買的金券在第i天賣掉再加上第j天剩下的錢最優。這是不可能的,要麼在第j天把所有錢全部買成金券,要麼一點不買,不可能有折中的情況是最優的。這個dp的複雜付o(n^2),下面進行優化。

(2)上面的dp方程其實就是求p=ai*yi+bi*xi的最大值,我們將(xi,yi)看做座標上的點,那麼得到:y=-bi/ai*x+p/ai,要使得p最大,也就是在y軸的截距最大。顯然,這個直線的斜率小於0。這個(xi,yi)來自之前的i-1個已經計算出的f值,我們就是要在這i-1個中找到乙個(xi,yi)使得p最大。我們可以看做將y=-bi/ai*x+p/ai這條直線從y軸正無窮向下平移,首先碰到的點就是使得p最大的點,那麼我們就是要將之前的點維護成乙個上凸殼,使得相鄰的斜率單調遞減,且支援插入更新、查詢,用splay維護,按照x座標。每次查詢時,找到跟當前斜率-bi/ai最接近的點即是最優的;插入時,按照插入的x座標找到其應該插入的位置。然後判斷要不要插入,找到其前驅pre和後繼next,若與其前驅的斜率小於與其後繼的斜率,那麼無需插入;否則插入,然後更新。比如對於前驅pre和前驅的前驅pre1,若pre1和當前點的斜率大於pre1和pre的斜率,那麼pre需要刪除。

double a[n],b[n],rate[n];

int n;

int c[n][2],p[n],root;

double x[n],y[n],slope[n];

void zig(int x)

p[x]=p[y];

p[y]=x;

}void zag(int x)

p[x]=p[y];

p[y]=x;

}void splay(int x,int goal)

else

}else

}if(!goal) root=x;

}int pre(int u)

int next(int u)

double get(int now)

else

}while(slope[i]

splay(i,0);

return x[i]*b[now]+y[i]*a[now];

}inline void del(int x)

void insert(double x,double y)

else

}x[++n]=x; y[n]=y; p[n]=i;

if(x>x[i]) c[i][1]=n;

else c[i][0]=n;

i=pre(n),j=next(n);

if(i&&j&&atan2(y-y[i],x-x[i])

temp=pre(i);

while(temp&&atan2(y-y[i],x-x[i])>=slope[i])

if(i) slope[n]=atan2(y-y[i],x-x[i]);

temp=next(j);

while(temp&&atan2(y[j]-y,x[j]-x)<=slope[temp])

if(j) slope[j]=atan2(y[j]-y,x[j]-x);

}int m;

double s;

int main()

printf("%.3lf\n",ans);

return 0;}

BZOJ1492 NOI2007 貨幣兌換

time limit 5 sec memory limit 64 mb submit 4914 solved 2026 submit status discuss 小y最近在一家金券交易所工作。該金券交易所只發行交易兩種金券 a紀念券 以下簡稱a券 和 b紀念券 以下 簡稱b券 每個持有金券的顧客都...

BZOJ1492 NOI2007 貨幣兌換

小y最近在一家金券交易所工作。該金券交易所只發行交易兩種金券 a紀念券 以下簡稱a券 和 b紀念券 以下 簡稱b券 每個持有金券的顧客都有乙個自己的帳戶。金券的數目可以是乙個實數。每天隨著市場的起伏波動,兩種金券都有自己當時的價值,即每一單位金券當天可以兌換的人民幣數目。我們記錄第 k 天中 a券 ...

bzoj1492 NOI2007 貨幣兌換Cash

time limit 5 secmemory limit 64 mb submit 3373solved 1424小y最近在一家金券交易所工作。該金券交易所只發行交易兩種金券 a紀念券 以下簡稱a券 和 b紀念券 以下簡稱b券 每個持有金券的顧客都有乙個自己的帳戶。金券的數目可以是乙個實數。每天隨著...