TLE on #10求助
查看原帖
TLE on #10求助
122298
Azote楼主2024/1/6 10:47

是写假了吗,本机上能跑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;
}

2024/1/6 10:47
加载中...