李超树做法求助
查看原帖
李超树做法求助
554746
yiming564楼主2024/9/28 17:06

推出的式子是 fiai=fjAj+fjBjbiai\dfrac{f_i}{a_i} = f_j A_j + f_j B_j \dfrac{b_i}{a_i},用李超树维护凸包,对 x=biaix = \dfrac{b_i}{a_i} 做了离散化,感觉没有错误。

代码如下:

#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;
}
2024/9/28 17:06
加载中...