BZOJ 1492 斜率优化dp && cdq分治
2015-01-29 20:14
471 查看
很容易得出转移方程,f[i]=max{ans,Rate[j]*F[j]*A[i]+F[j]*B[i]}/(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],求最大截距
嗯,平衡树上吧
鉴于那个时候还没有set,splay写起来就是要死要死的,那么我们还可以使用cdq分治,说起来简单,还不如直接写动态凸包
然后,我们发现会超时,我们稍微化简一下,由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 <cstdio> #include <cmath> #include <set> #include <iostream> 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 { double x,y,k; bool operator < (const point &rhs) const { if (!F) return x < rhs.x || (x == rhs.x && y < rhs.y); else return k > rhs.k; } point() {} point(double _x,double _y,double _k):x(_x),y(_y),k(_k){} }; typedef point Vector; Vector operator + (Vector A,Vector B){return (Vector){A.x+B.x,A.y+B.y,0};} Vector operator - (point A,point B){return (Vector){A.x-B.x,A.y-B.y,0};} inline double cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;} set <point> S; set <point> :: iterator it1,it2; inline double slope(point A,point B) { return (A.y-B.y)/(A.x-B.x); } inline double cut(double k,point p) { return p.y-p.x*k; } bool judge(point p) { F = false; if (S.size() == 1) return false; if (p < *S.begin() || *(--S.end()) < p) return false; it1 = it2 = S.lower_bound(p); it1--; if (cross(*it2-*it1,p-*it1) < 0) return true; return false; } void insert(point p) { if (judge(p)) return; it1 = it2 = --S.lower_bound(p); if (it2 != S.begin()) it2--; while (it1 != S.begin()) { if (cross(p-*it2,*it1-*it2) < 0) S.erase(it1); else break; it1 = it2; if (it2 != S.begin()) it2--; } it1 = it2 = S.lower_bound(p); it2++; while (it1 != S.end() && it2 != S.end()) { if (cross(p-*it2,*it1-*it2) > 0) S.erase(it1); else break; it1 = it2; if (it2 != S.end()) it2++; } it1 = it2 = S.lower_bound(p); if (it1 != S.begin()) { it1--; point temp = *it1; temp.k = slope(temp,p), S.erase(it1), S.insert(temp); } if (it2 != S.end()) { point temp = *it2; p.k = slope(temp,p); } S.insert(p); point temp = *(--S.end()); temp.k = INF; S.erase(--S.end()), S.insert(temp); } int main() { scanf("%d%lf",&n,&s); for (int i=1;i<=n;i++) scanf("%lf%lf%lf",&A[i],&B[i],&rate[i]); ans = s; f[1] = ans/(rate[1]*A[1]+B[1]); S.insert((point){f[1],f[1]*rate[1],INF}); for (int i=2;i<=n;i++) { F = true; point temp; temp = *S.lower_bound((point){0,0,-B[i]/A[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){0,0,-B[i]/A[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]); insert((point){f[i],f[i]*rate[i],0}); } printf("%.3lf\n",ans); return 0; }
鉴于那个时候还没有set,splay写起来就是要死要死的,那么我们还可以使用cdq分治,说起来简单,还不如直接写动态凸包
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstdlib> 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 { double x,y; bool operator < (const point &rhs) const { return x < rhs.x || (x == rhs.x && y < rhs.y); } }; typedef point Vector; Vector operator + (Vector A,Vector B){return (Vector){A.x+B.x,A.y+B.y};} Vector operator - (point A,point B){return (Vector){A.x-B.x,A.y-B.y};} inline double cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;} int convex_size; point P[MAXN]; point convex[MAXN]; inline double slope(point A,point B) { return (A.y-B.y)/(A.x-B.x); } inline double cut(double k,point p) { return p.y-p.x*k; } int find(double k) { int l = 1, r = convex_size-1; while (l+1 != r && l < r) { int mid = (l+r)/2; if (slope(convex[mid],convex[mid+1]) < k) r = mid; else l = mid; } return l; } void solve(int l,int r) { if (l == r) { int t = find(-B[l]/A[l]); f[l] = max(f[l]*(rate[l]*A[l]+B[l]),cut(-B[l]/A[l],convex[t])*A[l])/(rate[l]*A[l]+B[l]); ans = max(ans,f[l]*rate[l]*A[l]+f[l]*B[l]); if (t != convex_size-1) t++; f[l] = max(f[l]*(rate[l]*A[l]+B[l]),cut(-B[l]/A[l],convex[t])*A[l])/(rate[l]*A[l]+B[l]); f[l] = max(f[l],ans/(rate[l]*A[l]+B[l])); ans = max(ans,f[l]*rate[l]*A[l]+f[l]*B[l]); P[l] = (point){f[l],f[l]*rate[l]}; return; } int mid = (l+r)/2; solve(l,mid); convex_size = 0; for (int i=l;i<=mid;i++) { while (convex_size > 1 && (cross(convex[convex_size]-convex[convex_size-1],P[i]-convex[convex_size-1])) > 0) convex_size--; convex[++convex_size] = P[i]; } convex[++convex_size] = (point){INF,INF}; for (int i=mid+1;i<=r;i++) { int t = find(-B[i]/A[i]); f[i] = max(f[i]*(rate[i]*A[i]+B[i]),cut(-B[i]/A[i],convex[t])*A[i])/(rate[i]*A[i]+B[i]); if (t != convex_size-1) t++; f[i] = max(f[i]*(rate[i]*A[i]+B[i]),cut(-B[i]/A[i],convex[t])*A[i])/(rate[i]*A[i]+B[i]); } solve(mid+1,r); inplace_merge(P+l,P+mid+1,P+r+1); } int main() { scanf("%d%lf",&n,&s); for (int i=1;i<=n;i++) scanf("%lf%lf%lf",&A[i],&B[i],&rate[i]); ans = s; solve(1,n); printf("%.3lf\n",ans); return 0; }
相关文章推荐
- BZOJ 1492: [NOI2007]货币兑换Cash [CDQ分治 斜率优化DP]
- BZOJ1492:[NOI2007]货币兑换 (CDQ分治+斜率优化DP | splay动态维护凸包)
- BZOJ 1492 货币兑换Cash(CDQ分治+斜率优化dp)
- [BZOJ1492][NOI2007]货币兑换Cash(斜率优化dp+splay|cdq分治维护凸包)
- [BZOJ1492][NOI2007][CDQ分治][斜率优化][DP]货币兑换Cash
- [BZOJ 1492][NOI2007]货币兑换Cash:CDQ分治|DP斜率优化
- [BZOJ1492][NOI2007]货币兑换Cash && CDQ分治+斜率优化
- [DP 斜率优化 CDQ分治||动态维护凸包] BZOJ 1492 [NOI2007]货币兑换Cash
- 斜率优化(CDQ分治,Splay平衡树):BZOJ 1492: [NOI2007]货币兑换Cash
- bzoj1492 斜率优化|cdq分治
- BZOJ_1492_[NOI2007]货币兑换Cash_CDQ分治+斜率优化
- [BZOJ3672][NOI2014]购票-点分治-CDQ分治-斜率优化DP
- [BZOJ3963][WF2011][CDQ分治][斜率优化][DP]MachineWorks
- [BZOJ 3963][WF2011]MachineWorks:CDQ分治|DP斜率优化
- BZOJ1492:[NOI2007]货币兑换Cash (CDQ分治+斜率优化DP/平衡树维护凸壳)
- bzoj3672 [ NOI2014 ] -- 树上CDQ分治 + 斜率优化DP
- 【bzoj1492】【NOI2007】【货币兑换】【斜率优化+cdq分治】
- NOI 2007 货币兑换Cash (bzoj 1492) - 斜率优化 - 动态规划 - CDQ分治
- 【BZOJ1492】[NOI2007]货币兑换Cash 斜率优化+cdq分治
- BZOJ 3963: [WF2011]MachineWorks [CDQ分治 斜率优化DP]