BZOJ1492 [NOI2007]货币兑换Cash
cdq分治第二题。 最初没看清题所以一直不会做。晕。 cdq教程里的模板题。 显然所有卖都是卖完,买都是把钱买光。 f[i]表示第i天结束后最多持有b卷的数量,ans表示当前最多能赚到的rmb。 方程是: f[i] = max(ans, f[j] * r[j] * a[i] + f[j] * b[i]) / (a[i] * r[i] + b[i])。 移项得: f[j] = -(a[i]/b[i]) * (r[j] * f[j]) + (r[i] * a[i] + b[i]) / b[i] * f[j]。 把r[j]*f[j]看作x,把f[j]看作y,好像可以斜率优化了。 不急,f[j]好像没有单调性吧?不对,好像a[i]/b[i]也没有单调性!? 平衡树维护凸壳?想起了上回那道hnoi的作业,调了一晚上,怎么能这样。 然后,其实可以cdq。 每次对右边有影响的是左边的凸壳,所以先跑左边,计算左边对右边的影响,再跑右边。这回是中序遍历,而不是Mokia那题的后序。 原来cdq可以这么神奇。 然后又把凸壳写丑了TT。 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 100009; double ans, s, f[maxn], a[maxn], b[maxn], r[maxn]; int n, h[maxn], tmp[maxn], t; inline double getx(const int& i) { return f[i] * r[i]; } inline double gety(const int& i) { return f[i];...