Code:
#include<bits/stdc++.h> #define maxn 300000 #define inf 0x3f3f3f3f #define setIO(s) freopen(s".in","r",stdin) using namespace std; const double eps = 1e-9; int root; struct Splaytree { #define get(x) (ch[f[x]][1]==x) int cnt; int f[maxn],ch[maxn][2]; double X[maxn],Y[maxn],lk[maxn],rk[maxn]; inline void rotate(int x) { int old=f[x],fold=f[old],which=get(x); ch[old][which]=ch[x][which^1],f[ch[old][which]]=old; ch[x][which^1]=old,f[old]=x,f[x]=fold; if(fold) ch[fold][ch[fold][1]==old]=x; } inline void splay(int x,int &tar) { int fa,u=f[tar]; for(;(fa=f[x])!=u;rotate(x)) if(f[fa]!=u) rotate(get(fa)==get(x)?fa:x); tar=x; } inline double slope(int i,int j) { return fabs(X[i]-X[j])<=eps ? -inf : (Y[i]-Y[j])/(X[i]-X[j]); } inline void insert(int &o,double x,double y,int last) { if(!o) { o=++cnt; X[o]=x,Y[o]=y,f[o]=last; return; } insert(ch[o][x-X[o]>eps],x,y,o); } inline int pre(int x) { int cur=ch[x][0],re=0; while(cur) { if(slope(x,cur)+eps>=rk[cur]) re=cur,cur=ch[cur][0]; else cur=ch[cur][1]; } return re; } inline int nxt(int x) { int cur=ch[x][1],re=0; while(cur) { if(slope(x,cur)<=lk[cur]+eps) re=cur,cur=ch[cur][1]; else cur=ch[cur][0]; } return re; } inline int getl(int x) { while(ch[x][0]) x=ch[x][0]; return x; } inline int getr(int x) { while(ch[x][1]) x=ch[x][1]; return x; } inline void del(int x) { if(!ch[x][0]) { int right=getl(ch[x][1]); splay(right,ch[x][1]),root=right; ch[x][1]=f[root]=0; lk[root]=inf; } else if(!ch[x][1]) { int left=ch[x][0]; splay(left,ch[x][0]),root=left; ch[x][0]=f[root]=0; rk[root]=-inf; } else { int right=getl(ch[x][1]); int left=getr(ch[x][0]); splay(left,ch[x][0]); splay(right,ch[x][1]); root=left; ch[root][1]=right,f[right]=root; rk[root]=lk[right]=slope(root,right); } } inline void maintain(int x) { splay(x,root); if(ch[x][0]) { int left=pre(x); if(left) { splay(left,ch[x][0]); ch[left][1]=f[ch[left][1]]=0; rk[left]=lk[x]=slope(left,x); } else lk[x]=-inf; } else lk[x]=inf; if(ch[x][1]) { int right=nxt(x); if(right) { splay(right,ch[x][1]); ch[right][0]=f[ch[right][0]]=0; rk[x]=lk[right]=slope(right,x); } else rk[x]=inf; } else rk[x]=-inf; if(lk[x]-rk[x]<=eps) del(x); } inline int getans(int x,double k) { if(!x) return 0; if(lk[x]+eps>=k&&rk[x]<=k+eps) return x; if(lk[x]<k+eps) return getans(ch[x][0],k); else return getans(ch[x][1],k); } }splay; int n,S; double f[maxn],A[maxn],B[maxn],rate[maxn]; int main() { int i,j; // setIO("input"); scanf("%d%lf",&n,&f[0]); for(i=1;i<=n;++i) { scanf("%lf%lf%lf",&A[i],&B[i],&rate[i]); int j=splay.getans(root,-(A[i]/B[i])); double x=splay.X[j],y=splay.Y[j]; f[i]=max(f[i-1],A[i]*x+B[i]*y); y=f[i]/(A[i]*rate[i]+B[i]); x=y*rate[i]; splay.insert(root,x,y,0); splay.maintain(i); } printf("%.3lf",f[n]); return 0; }
BZOJ 1492: [NOI2007]货币兑换Cash 斜率优化 + splay动态维护凸包
原文:https://www.cnblogs.com/guangheli/p/11149096.html