1. 程式人生 > >bzoj [NOI2007]貨幣兌換Cash (cdq分治+斜率優化 )

bzoj [NOI2007]貨幣兌換Cash (cdq分治+斜率優化 )

#include<cstdio>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<cstring>
#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
#include<stdlib.h>
#include<set>
#include<ctime>
#include<cmath>
#include<iomanip>
using namespace std;
typedef long long LL;
const int mmax  = 100010;
const int inf = 0x3fffffff;
const double eps = 1e-8;
double A[mmax],B[mmax],R[mmax];
double f[mmax];
double dp[mmax];


int sgn(double x)// ·ûºÅº¯Êý
{
    if(fabs(x)<eps)
        return 0;
    return x<0?-1:1;
}


struct Point
{
    double x,y;
    Point(double x=0.0,double y=0.0):x(x),y(y) {}
    void read()
    {
        scanf("%lf %lf",&x,&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);
}
Vector operator * (Vector A,double p)
{
    return Vector(A.x*p,A.y*p);
}
Vector operator / (Vector A,double p)
{
    return Vector(A.x/p,A.y/p);
}

bool operator < (const Point &a,const Point &b)
{
    return a.x<b.x || (a.x==b.x&&a.y<b.y);
}
//ÔËË㲿·Ö
double Dot(Vector A,Vector B)
{
    return A.x*B.x+A.y*B.y;
}
double Cross(Vector A,Vector B)
{
    return A.x*B.y-A.y*B.x;
}



double x(int i)
{
    return dp[i]*R[i]/f[i];
}
double y(int i)
{
    return dp[i]/f[i];
}

bool cmp(int i,int j)
{
    return A[i]*B[j]>A[j]*B[i];
}

int ConvexHull(Point *p,int n,Point *Poly)
{
    sort(p,p+n);
    int m=0;
    for(int i=n-1;i>=0;i--)
    {
        while(m>1 && Cross(Poly[m-1]-Poly[m-2],p[i]-Poly[m-2]) <=0 ) m--;
        Poly[m++]=p[i];
    }
    return m;
}
Point P[mmax],Poly[mmax];
int tmp[mmax];
void cdq(int l,int r)
{
    if(l==r)
    {
        dp[l]=max(dp[l],dp[l-1]);
        return ;
    }

    int mid=(l+r)>>1;
    cdq(l,mid);
    int cnt=0;
    for(int i=l;i<=mid;i++)
        P[cnt++]=Point(x(i),y(i));


    cnt=ConvexHull(P,cnt,Poly);
    for(int i=mid+1;i<=r;i++)
        tmp[i]=i;
    sort(tmp+mid+1,tmp+r+1,cmp);

    int i=0,j=mid+1;

    while(j<=r)
    {
        while(i<cnt-1 && (Poly[i].y-Poly[i+1].y )*B[tmp[j]] < -1.0*(Poly[i].x-Poly[i+1].x)*A[tmp[j]]  )
            i++;
        dp[tmp[j]]=max(dp[tmp[j]],A[tmp[j]]*Poly[i].x+B[tmp[j]]*Poly[i].y);
        j++;
    }
    cdq(mid+1,r);

}
int main()
{

    int n,s;
    cin>>n>>s;
    for(int i=1;i<=n;i++)
    {
        scanf("%lf %lf %lf",&A[i],&B[i],&R[i]);
        f[i]=A[i]*R[i]+B[i];
    }
    memset(dp,0,sizeof dp);
    dp[0]=1.0*s;
    cdq(1,n);

    double ans=0;
    for(int i=1;i<=n;i++)
        ans=max(ans,dp[i]);
    printf("%.3lf\n",ans);

    return 0;
}