bzoj1492 [NOI2007]货币兑换Cash【cdq分治】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1492

推荐博客:http://www.cnblogs.com/zig-zag/archive/2013/04/24/3039418.html

保存cdq分治模版代码。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>

const int maxn = 100005;
const double eps = 1e-9, inf = 1e300;

int n, s;
double a[maxn], b[maxn], rate[maxn], f[maxn];

struct point {
	double x, y;
	int id;
	bool operator<(const point & rhs) const {
		if (fabs(x - rhs.x) < eps) {
			return y > rhs.y + eps;
		}
		return x + eps < rhs.x;
	}
} stk[maxn], p[maxn], np[maxn];
struct query {
	double k;
	int id;
} q[maxn], tq[maxn];

bool cmp(const query & aa, const query & ss) {
	return aa.k > ss.k;
}
inline double getk(const point & aa, const point & ss) {
	if (fabs(aa.x - ss.x) < eps) {
		return -inf;
	}
	return (ss.y - aa.y) / (ss.x - aa.x);
}

void slove(int left, int right) {
	if (left == right) {
		f[left] = std::max(f[left], f[left - 1]);
		p[left].y = f[left] / (a[left] * rate[left] + b[left]);
		p[left].x = p[left].y * rate[left];
		return;
	}
	
	int mid = (left + right) >> 1, idx1 = left, idx2 = mid + 1;
	for (int i = left; i <= right; ++i) {
		if (q[i].id <= mid) {
			tq[idx1++] = q[i];
		}
		else {
			tq[idx2++] = q[i];
		}
	}
	memcpy(q + left, tq + left, sizeof(query) * (right - left + 1));
	
	slove(left, mid);
	
	int top = 0;
	stk[top++] = p[left];
	for (int i = left + 1; i <= mid; ++i) {
		while (top > 1 && getk(p[i], stk[top - 1]) > getk(stk[top - 1], stk[top - 2]) + eps) {
			--top;
		}
		stk[top++] = p[i];
	}
	
	int j = 0;
	for (int i = mid + 1; i <= right; ++i) {
		while (j < top - 1 && getk(stk[j], stk[j + 1]) > q[i].k + eps) {
			++j;
		}
		f[q[i].id] = std::max(f[q[i].id], stk[j].x * a[q[i].id] + stk[j].y * b[q[i].id]);
	}
	
	slove(mid + 1, right);
	
	idx1 = left, idx2 = mid + 1;
	for (int i = left; i <= right; ++i) {
		if (idx1 <= mid && (p[idx1] < p[idx2] || idx2 > right)) {
			np[i] = p[idx1++];
		}
		else {
			np[i] = p[idx2++];
		}
	}
	memcpy(p + left, np + left, sizeof(point) * (right - left + 1));
}

int main(void) {
	scanf("%d%d", &n, &s);
	f[0] = (double)s;
	for (int i = 1; i <= n; ++i) {
		scanf("%lf%lf%lf", a + i, b + i, rate + i);
		q[i] = (query){-a[i] / b[i], i};
	}
	
	std::sort(q + 1, q + n + 1, cmp);
	slove(1, n);
	printf("%.3lf\n", f[n]);
	return 0;
}

  

posted @ 2017-04-12 19:46  ciao_sora  阅读(158)  评论(0编辑  收藏  举报