BZOJ 1492 斜率優化dp cdq分治

2021-06-28 12:00:23 字數 2882 閱讀 1581

很容易得出轉移方程,f[i]=max/(rate[i]*a[i]+b[i]),其中f[i]表示在第i天所獲得的的最多的b卷

然後,我們發現會超時,我們稍微化簡一下,由f[i] = (rate[j]*f[j]*a[i]+f[j]*b[i])/(rate[i]*a[i]+b[i])得

f[i]*(rate[i]*a[i]+b[i])/a[i] = (-b[i]/a[i])*f[j]+f[j]*rate[j]

相當於我們需要維護乙個資料結構,滿足

1.插入乙個點(f[i],f[i]*rate[i])

2.給定負斜率-b[i]/a[i],求最大截距

嗯,平衡樹上吧

#include #include #include #include using namespace std;

const int maxn = 100001;

const double inf = 10000001;

int n;

double s;

double f[maxn];

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

double ans;

bool f;

struct point

point() {}

point(double _x,double _y,double _k):x(_x),y(_y),k(_k){}

};typedef point vector;

vector operator + (vector a,vector b);}

vector operator - (point a,point b);}

inline double cross(vector a,vector b)

set s;

set :: iterator it1,it2;

inline double slope(point a,point b)

inline double cut(double k,point p)

bool judge(point p)

void insert(point p)

it1 = it2 = s.lower_bound(p);

it2++;

while (it1 != s.end() && it2 != s.end())

it1 = it2 = s.lower_bound(p);

if (it1 != s.begin())

if (it2 != s.end())

s.insert(p);

point temp = *(--s.end());

temp.k = inf;

s.erase(--s.end()), s.insert(temp);

}int main()

); for (int i=2;i<=n;i++)

); f[i] = max(ans,cut(-b[i]/a[i],temp)*a[i])/(rate[i]*a[i]+b[i]);

ans = max(ans,rate[i]*f[i]*a[i]+f[i]*b[i]);

temp = *--s.lower_bound((point));

f[i] = max(ans,cut(-b[i]/a[i],temp)*a[i])/(rate[i]*a[i]+b[i]);

ans = max(ans,rate[i]*f[i]*a[i]+f[i]*b[i]);

insert((point));

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

return 0;

}

鑑於那個時候還沒有set,splay寫起來就是要死要死的,那麼我們還可以使用cdq分治,說起來簡單,還不如直接寫動態凸包

#include #include #include #include #include using namespace std;

const int maxn = 100001;

const double inf = 10000001;

int n;

double s;

double f[maxn];

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

double ans;

bool f;

struct point

};typedef point vector;

vector operator + (vector a,vector b);}

vector operator - (point a,point b);}

inline double cross(vector a,vector b)

int convex_size;

point p[maxn];

point convex[maxn];

inline double slope(point a,point b)

inline double cut(double k,point p)

int find(double k)

return l;

}void solve(int l,int r)

; return;

} int mid = (l+r)/2;

solve(l,mid);

convex_size = 0;

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

convex[++convex_size] = (point);

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

solve(mid+1,r);

inplace_merge(p+l,p+mid+1,p+r+1);

}int main()

BZOJ 1492 貨幣兌換Cash

題意 有ab兩種金券,n天,第一天某人有s的錢。給出每天的三個值ai,bi,ratei。每天可以進行的操作有兩種 1 賣掉x 0 x 100 意味著分別將a種金券和b種金券分別賣掉x 分別為ai,bi 2 買進x元的金券 分別以ai bi的 買進兩種金券買進的數量比為ratei。一天內可以進行多次操...

bzoj4578 斜率優化

方法麻煩了,簡單方法見 include include include include include includeusing namespace std typedef long long ll const ll inf 1e15 ll dp 3005 3005 sum 3005 int n,m...

斜率優化bzoj 1597

看到題目,時間複雜度至少是o n logn o nlogn o nlog n 或o n sqrt n o nsqrt n o nsqr t n 前者的概率較大,此題有計算內乘積,應該與分塊無關 早就知道是斜率優化 假設長為a aa值,寬為bbb值 觀察題目,可以猜想一下決策會不會有連續性,猜想決策可...