1492: [NOI2007]货币兑换Cash|动态规划|cdq分治

来源:互联网 发布:vr软件app 编辑:程序博客网 时间:2024/04/28 05:37

好厉害的分治贴代码

可以参考论文

#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 1e9using 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;}


0 0