是写假了吗,本机上能跑700ms,洛谷1500ms起步
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define x first
#define y second
typedef std::pair<double, double> PDD;
const double eps = 2.7e-5, pi = acos(-1), INF = 5e4 + 5;
const int N = 510;
struct Circle
{
PDD p;
double r;
} c[N];
struct polygon
{
PDD v[4];
} p[N];
int n;
double alpha, h[N], hsum;
PDD stk[N << 1];
int dcmp(double a, double b)
{
if (fabs(a - b) < eps)
return 0;
if (a < b)
return -1;
return 1;
}
int sign(double a)
{
if (fabs(a) < eps)
return 0;
if (a < 0)
return -1;
return 1;
}
PDD operator-(PDD a, PDD b)
{
return {a.x - b.x, a.y - b.y};
}
PDD operator+(PDD a, PDD b)
{
return {a.x + b.x, a.y + b.y};
}
PDD operator*(PDD a, double b)
{
return {a.x * b, a.y * b};
}
PDD operator/(PDD a, double b)
{
return {a.x / b, a.y / b};
}
double operator&(PDD a, PDD b)
{
return a.x * b.x + a.y * b.y;
}
double cross(PDD a, PDD b)
{
return a.x * b.y - a.y * b.x;
}
double area(PDD a, PDD b, PDD c)
{
return cross(b - a, c - a);
}
double getlen(PDD a)
{
return sqrt(a & a);
}
PDD norm(PDD a)
{
return a / getlen(a);
}
PDD rotate(PDD a, double b)
{
double cs = cos(b), sn = sin(b);
return {a.x * cs + a.y * sn, -a.x * sn + a.y * cs};
}
double get_dist(PDD a, PDD b)
{
auto d = b - a;
return getlen(d);
}
bool intersection(PDD a, PDD b, PDD c, PDD d)
{
if (!sign(cross(b - a, d - c)))
return false;
return (sign(area(a, b, c) * area(a, b, d)) < 0) && (sign(area(c, d, a) * area(c, d, b)) < 0);
}
PDD get_line_intersection(PDD a, PDD b, PDD c, PDD d)
{
auto x = b - a, y = d - c;
auto u = a - c;
double t = cross(y, u) / cross(x, y);
return a + x * t;
}
int top;
double f(double x)
{
top = 0;
for (int i = 1; i <= n; ++i)
{
auto &p = c[i];
double dist = fabs(p.p.x - x);
if (dcmp(dist, p.r) < 0)
{
double len = sqrt(p.r * p.r - dist * dist);
stk[++top] = {p.p.y - len, p.p.y + len};
}
auto &t = ::p[i];
int u = 0;
double d[5];
for (int j = 0; j < 3; ++j)
{
if (!intersection({x, -INF}, {x, INF}, t.v[j], t.v[j + 1]))
continue;
auto o = get_line_intersection({x, -INF}, {x, INF}, t.v[j], t.v[j + 1]);
d[++u] = o.y;
}
if (u)
{
std::sort(d + 1, d + 1 + u);
stk[++top] = {d[1], d[u]};
}
}
std::sort(stk + 1, stk + top + 1);
static double res, st, ed;
res = 0, st = -INF, ed = -INF;
for (int i = 1; i <= top; ++i)
{
// if (dcmp(stk[i].y, ed) <= 0)
// continue;
// if (dcmp(stk[i].x, ed) <= 0)
// ed = stk[i].y;
if (stk[i].y <= ed)
continue;
if (stk[i].x <= ed)
ed = stk[i].y;
else
{
res += ed - st, st = stk[i].x, ed = stk[i].y;
}
}
res += ed - st;
return res;
}
double simpson(double l, double r)
{
return (f(l) + f((l + r) / 2) * 4 + f(r)) * (r - l) / 6;
}
double divide(double l, double r)
{
double mid = (l + r) / 2;
static double sl, sr, s;
sl = simpson(l, mid), sr = simpson(mid, r), s = simpson(l, r);
if (fabs(s - sl - sr) < eps)
return sl + sr;
return divide(l, mid) + divide(mid, r);
}
int main()
{
scanf("%d%lf", &n, &alpha);
for (int i = 0; i <= n; ++i)
{
scanf("%lf", &h[i]);
if (i)
c[i].p = {0, h[i - 1] / tan(alpha)};
h[i] += h[i - 1];
if (i)
{
p[i].v[3].y = h[i] / tan(alpha);
p[i].v[0].y = c[i].p.y;
}
}
for (int i = 1; i <= n; ++i)
scanf("%lf", &c[i].r);
c[n + 1] = {{0, h[n]}, 0};
for (int i = 1; i < n; ++i)
{
double AC = (h[i] - h[i - 1]) / tan(alpha), AE = c[i].r, CF = c[i + 1].r;
if (AE == CF)
p[i].v[1].x = p[i].v[2].x = AE, p[i].v[1].y = c[i].p.y, p[i].v[2].y = c[i + 1].p.y;
else if (AE > CF)
{
double CG = (AE - CF) * CF / AC;
double len = sqrt(CF * CF - CG * CG);
p[i].v[2] = {len, c[i + 1].p.y + CG};
double AT = sqrt(AC * AC - (CF - AE) * (CF - AE));
auto f = norm(c[i + 1].p - p[i].v[2]);
f = rotate(f, -pi / 2);
p[i].v[1] = p[i].v[2] + f * AT;
}
else
{
double AG = (CF - AE) * AE / AC;
double len = sqrt(AE * AE - AG * AG);
p[i].v[1] = {len, c[i].p.y - AG};
double CT = sqrt(AC * AC - (CF - AE) * (CF - AE));
auto f = norm(c[i].p - p[i].v[1]);
f = rotate(f, pi / 2);
p[i].v[2] = p[i].v[1] + f * CT;
}
}
double AC = (h[n] - h[n - 1]) / tan(alpha);
p[n].v[2] = p[n].v[3];
double CG = sqrt(AC * AC - c[n].r * c[n].r);
double tanCAG = CG / c[n].r;
auto f = norm(PDD{c[n].r, c[n].r / tanCAG + c[n].p.y} - c[n].p);
p[n].v[1] = p[n].v[0] + f * c[n].r;
double R = 0;
for (int i = 1; i <= n; ++i)
R = std::max(R, c[i].r);
printf("%.2lf", divide(0, R) * 2);
return 0;
}