[ZJOI2008]瞭望塔

用每条相邻两点所构成的直线维护一个下凸。

主要注意凸包的点与地面的高度差,地面的拐点与凸包的高度差。

/**

 * Problem:[JLOI2013]Tower

 * Author:Shun Yao

 * Time:2013.5.30

 * Result:Accepted

 */



#include <cstring>

#include <cstdlib>

#include <cstdio>

#include <algorithm>



const long Maxn = 305;



double abs(double x) {

	return x < 0 ? -x : x;

}



long cmp(double x, double y) {

	if (abs(x - y) < 1e-8)

		return 0;

	if (x < y)

		return -1;

	return 1;

}



double min(double x, double y) {

	return x < y ? x : y;

}



class pnode {

public:

	double x, y;

	pnode() {}

	~pnode() {}

} p[Maxn];



class qnode {

public:

	double k, b, x;

	qnode() {}

	~qnode() {}

} q[Maxn], *ql, *qq;



bool cmpk(qnode x, qnode y) {

	return cmp(x.k, y.k) == 0 ? x.b > y.b : x.k < y.k;

}



bool cmpkk(qnode x, qnode y) {

	return cmp(x.k, y.k) == 0;

}



double cross(qnode x, qnode y) {

	return (x.b - y.b) / (y.k - x.k);

}



int main() {

	static long n, i, nn;

	static double ans;

	freopen("tower.in", "r", stdin);

	freopen("tower.out", "w", stdout);

	scanf("%ld", &n);

	for (i = 1; i <= n; ++i)

		scanf("%lf", &p[i].x);

	for (i = 1; i <= n; ++i)

		scanf("%lf", &p[i].y);

	for (i = 1; i < n; ++i) {

		q[i].k = (p[i].y - p[i + 1].y) / (p[i].x - p[i + 1].x);

		q[i].b = -q[i].k * p[i].x + p[i].y;

	}

	std::sort(ql = q + 1, q + n, cmpk);

	nn = std::unique(q + 1, q + n, cmpkk) - q;

	for (qq = ql + 1; qq != q + nn; ++qq) {

		while (ql > q + 1 && cmp(cross(*qq, *(ql - 1)), (*ql).x) <= 0)

			--ql;

		*(++ql) = *qq;

		(*ql).x = cross(*ql, *(ql - 1));

	}

	i = 1;

	ans = 1e20;

	for (qq = q + 1; qq != ql; ++qq) {

		while (i <= n && cmp(p[i].x, (*(qq + 1)).x) <= 0) {

			ans = min(ans, abs(p[i].x * (*qq).k + (*qq).b - p[i].y));

			++i;

		}

		if (i > n)

			break;

		if (i > 1)

			ans = min(ans, abs((*(qq + 1)).x * (*(qq + 1)).k + (*(qq + 1)).b - ((p[i].y - p[i - 1].y) / (p[i].x - p[i - 1].x) * ((*(qq + 1)).x - p[i].x) + p[i].y)));

	}

	while (i <= n) {

		ans = min(ans, abs(p[i].x * (*qq).k + (*qq).b - p[i].y));

		++i;

	}

	printf("%.3lf", ans);

	fclose(stdin);

	fclose(stdout);

	return 0;

}

 

你可能感兴趣的:(2008)