1492: [NOI2007]貨幣兌換Cash|動態規劃|cdq分治
阿新 • • 發佈:2019-02-01
好厲害的分治貼程式碼
可以參考論文
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<queue> #include<set> #include<map> #include<vector> #include<algorithm> #include<iostream> #define T 120000 #define eps 1e-9 #define inf 1e9 using namespace std; struct W { double x,y,k,a,b,rate; int id; }p[T],q[T],t[T]; double f[T]; int st[T]; int n; bool cmp(W a,W b){return a.k<b.k;} double getk(int i,int j) { if (i==0) return -inf; if (j==0) return inf; if (fabs(p[i].x-p[j].x)<=eps) return -inf; return (p[i].y-p[j].y)/(p[i].x-p[j].x); } void solve(int l,int r) { if(l==r) { f[l]=max(f[l],f[l-1]); p[l].y=f[l]/(q[l].a*q[l].rate+q[l].b); p[l].x=p[l].y*q[l].rate; return ; } int mid=l+r>>1,l1=l,l2=mid+1; for(int i=l;i<=r;i++) if(q[i].id<=mid) t[l1++]=q[i]; else t[l2++]=q[i]; for(int i=l;i<=r;i++) q[i]=t[i]; solve(l,mid); int top=0; for(int i=l;i<=mid;i++) { while(top>=2&&getk(i,st[top])>getk(st[top],st[top-1])) top--; st[++top]=i; } int j=1; for (int i=r;i>=mid+1;i--) { while (j<top&&q[i].k<getk(st[j],st[j+1])) j++; f[q[i].id]=max(f[q[i].id],p[st[j]].x*q[i].a+p[st[j]].y*q[i].b); } solve(mid+1,r); l1=l,l2=mid+1; for (int i=l;i<=r;i++) if ((p[l1].x<p[l2].x||l2>r)&&l1<=mid) t[i]=p[l1++]; else t[i]=p[l2++]; for (int i=l;i<=r;i++) p[i]=t[i]; } int main() { scanf("%d%lf",&n,&f[0]); for(int i=1;i<=n;i++) { scanf("%lf%lf%lf",&q[i].a,&q[i].b,&q[i].rate); q[i].k=-q[i].a/q[i].b; q[i].id=i; } sort(q+1,q+n+1,cmp); solve(1,n); printf("%.3lf\n",f[n]); return 0; }