此题非常的经典(似乎cdq分治就是从这题引出的)
基础思想就是cdq分治优化dp。
网上题解似乎很多。。
所以dp什么的就不写了。
重点就是通过cdq来满足斜率优化的条件(维护凸包)
#include <bits/stdc++.h>
#define gc getchar()
#define N 100009
#define mid (l+r>>1)
#define eps 1e-7
#define inf 1e10
using namespace std;
int n,s,sta[N];
double dp[N];
struct node
{
double k,a,b,r;
int pos;
bool operator <(const node &rhs) const
{
return k<rhs.k;
}
}q[N],now[N];
struct point
{
double x,y;
bool operator <(const point &rhs) const
{
return x<rhs.x||(fabs(x-rhs.x)<eps&&y<rhs.y);
}
}p[N],Now[N];
double get_k(int a,int b)
{
if (a==0||b==0) return -inf;
if (fabs(p[a].x-p[b].x)<eps) return -inf;
return (p[a].y-p[b].y)/(p[a].x-p[b].x);
}
void solve(int l,int r)
{
if (l==r)
{
dp[l]=max(dp[l-1],dp[l]);
p[l].y=dp[l]/(q[l].a*q[l].r+q[l].b);
p[l].x=p[l].y*q[l].r;
return;
}
int l1=l,l2=mid+1;
for (int i=l;i<=r;i++)
if (q[i].pos<=mid) now[l1++]=q[i];
else now[l2++]=q[i];
for (int i=l;i<=r;i++) q[i]=now[i];
solve(l,mid);
int top=0;
for (int i=l;i<=mid;i++)//k dijian
{
while (top>=2&&get_k(i,sta[top])>get_k(sta[top],sta[top-1])) top--;
sta[++top]=i;
}
int j=1;
for (int i=r;i>mid;i--)//k dijian
{
while (j<top&&q[i].k<get_k(sta[j],sta[j+1])) j++;
dp[q[i].pos]=max(dp[q[i].pos],q[i].a*p[sta[j]].x+q[i].b*p[sta[j]].y);
}
solve(mid+1,r);
l1=l,l2=mid+1;
for (int i=l;i<=r;i++)
if ((p[l1]<p[l2]||l2>r)&&l1<=mid) Now[i]=p[l1++];
else Now[i]=p[l2++];
for (int i=l;i<=r;i++)
p[i]=Now[i];
}
int main()
{
scanf("%d%lf",&n,&dp[0]);
for (int i=1;i<=n;i++)
{
scanf("%lf%lf%lf",&q[i].a,&q[i].b,&q[i].r);
q[i].k=-q[i].a/q[i].b,q[i].pos=i;
}
sort(q+1,q+n+1);
solve(1,n);
printf("%.3lf\n",dp[n]);
return 0;
}