P4027 NOI2007 貨幣兌換

2022-05-19 11:13:39 字數 1857 閱讀 2304

傳送門

首先有乙個顯然的貪心,每次操作都要做到底,為了最優不會出現只賣一部分或者只買一部分的操作

所以設 $f[i]$ 表示前 $i$ 天得到的最大價值,那麼對於每乙個 $i$,列舉所有 $j

顯然如果知道 $f[j]$,那麼就知道第 $j$  天**多少

設 $a$ 買了 $x$, $b$ 買了 $y$,那麼 $f[i]=a[i]*x+b[i]*y$

因為 $x,y$ 只和 $j$ 有關,顯然可以斜率優化

具體就是 $-a[i]*x+f[i]=b[i]*y$,同除乙個 $b[i]$,變成 $-a[i]/b[i]*x+f[i]/b[i]=y$

那麼 $k=-a[i]/b[i],x=x,b=f[i]/b[i],y=y$

自己推一下,容易得出 $x_i=f[i]*r[i]/(a[i]*r[i]+b[i]),y_i=f[i]/(a[i]*r[i]+b[i])$

然後因為 $k,x$ 都不單調,所以要用 $cdq$ 搞

先按斜率排序,然後 $cqd$ 分治之前按下標拆成兩部分,這個具體還是看**吧...

#include#include

#include

#include

#include

using

namespace

std;

typedef

long

long

ll;typedef

double

db;inline

intread()

while(ch>='

0'&&ch<='

9')

return x*f;

}const

int n=2e5+7,inf=1e9+7

;const db eps=1e-9

;int

n,s;

db f[n];

struct

dat}t[n],tmp[n];

inline db slope(

int i,int j)//

求斜率維護凸包

inline db cross(db xa,db ya,db xb,db yb) //

用叉積維護凸包會更快

inline void merge(int l,int r,int mid)//

按x歸併排序

for(int p=l;p<=r;p++) t[p]=tmp[p];

}int q[n];//

棧,維護凸包

void cdq(int l,int

r)

int mid=l+r>>1,pl=l,pr=mid+1,top=0

;

for(int p=l;p<=r;p++)//

按下標分開

for(int p=l;p<=r;p++) t[p]=tmp[p];

cdq(l,mid); q[

0]=0;//

先處理左邊

for(int i=l;i<=mid;i++)//

此時左邊全部更新完畢,可以維護左邊構成的凸包了

//注意此時左邊的t[i].x是有序的,因為每次cdq結束都會merge

for(int i=mid+1;i<=r;i++)//

用左邊構成的凸包更新右邊,此時右邊的斜率是有序的

cdq(mid+1,r); merge(l,r,mid);//

處理右邊後按x排序

}int

main()

sort(t+1,t+n+1); cdq(1,n);//

先按k排序再cdq

printf("

%.3lf

",f[n]);

return0;

}

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