用每条相邻两点所构成的直线维护一个下凸。
主要注意凸包的点与地面的高度差,地面的拐点与凸包的高度差。
/**
* 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;
}