推出的式子是 aifi=fjAj+fjBjaibi,用李超树维护凸包,对 x=aibi 做了离散化,感觉没有错误。
代码如下:
#include <bits/extc++.h>
#define inline __always_inline
#define lson(u) (son[(u)][0])
#define rson(u) (son[(u)][1])
template <typename T> inline void chkmax(T &x, const T &y) { if (x < y) x = y; }
template <typename T> inline void chkmin(T &x, const T &y) { if (x > y) x = y; }
const int MaxN = 1e5 + 5, MaxSGT = MaxN << 1;
const double eps = 0, inf = 1e50;
int n, lim;
double a[MaxN], b[MaxN], A[MaxN], B[MaxN], f[MaxN], map[MaxN], origin[MaxN], s, k;
struct line_t
{
double k, b;
inline double operator()(int x) { return k * map[x] + b; }
};
struct segment_tree_t
{
int son[MaxSGT][2], top = 2;
line_t line[MaxSGT];
void build(int u, int l, int r)
{
line[u] = {0, -inf}; if (r - l == 1) return;
build(lson(u) = top++, l, l + r >> 1);
build(rson(u) = top++, l + r >> 1, r);
}
void insert(int u, int l, int r, line_t f)
{
int mid = l + r >> 1;
if (line[u](mid) + eps < f(mid)) std::swap(line[u], f);
if (line[u](l) + eps < f(mid)) insert(lson(u), l, mid, f);
else if (line[u](r - 1) + eps < f(r - 1)) insert(rson(u), mid, r, f);
}
double max(int u, int l, int r, int x)
{
double ans = line[u](x); if (r - l == 1) return ans;
int mid = l + r >> 1;
if (x < mid) chkmax(ans, max(lson(u), l, mid, x));
else chkmax(ans, max(rson(u), mid, r, x));
return ans;
}
} tree;
int main()
{
freopen64("data/cash5.in", "r", stdin);
scanf("%d %lf", &n, &s);
for (int i = 1; i <= n; i++)
scanf("%lf %lf %lf", &a[i], &b[i], &k), B[i] = 1.0 / (k * a[i] + b[i]), A[i] = B[i] * k, origin[i] = map[i - 1] = b[i] / a[i];
std::sort(map, map + n);
lim = std::unique(map, map + n) - map;
double max = f[0] = s;
tree.build(1, 0, lim);
for (int i = 1; i <= n; i++)
{
f[i] = max;
int x = std::lower_bound(map, map + lim, origin[i]) - map;
chkmax(f[i], tree.max(1, 0, lim, x) * a[i]);
tree.insert(1, 0, lim, {f[i] * B[i], f[i] * A[i]});
chkmax(max, f[i]);
}
printf("%.3lf", f[n]);
return 0;
}