2 条题解

  • 1
    @ 2025-11-27 4:18:34

    P4642

    P4642 [BJWC2008] 方程

    (题目描述不如原题清晰)

    ... ... ...


    AC代码

    const int N = 100005;
    const f80 eps = 1e-10;
    const f64 INF_MARK = -1e18; // 使用一个极小值作为无解标记
    
    struct Line { i64 a, b, c; int id; } l[N], q[10005];
    typedef pair<f80, f80> Point;
    Point p[N];
    int stk[N];
    f64 ans[10005];
    
    inline bool cmp(const Line &x, const Line &y) {
        i64 tmp = x.a * y.b - x.b * y.a;
        if (tmp != 0) return tmp > 0;
        return (x.c * y.b - x.b * y.c) > 0;
    }
    
    inline Point Intersect(const Line &x, const Line &y) {
        i64 d = x.a * y.b - x.b * y.a;
        f80 px = (f80)x.c * y.b - (f80)x.b * y.c;
        f80 py = (f80)x.a * y.c - (f80)x.c * y.a;
        return make_pair(px / d, py / d);
    }
    
    inline bool PointOnLine(const Line &pl, const Point &pp) {
        return (pl.a * pp.first + pl.b * pp.second - pl.c) > -eps;
    }
    
    int main() {
        init();
        int n, m;
        read(n); read(m);
        for (int i = 1; i <= n; ++i) {
            read(l[i].a); read(l[i].b); read(l[i].c);
        }
        sort(l + 1, l + n + 1, cmp);
        int siz = 1;
        for (int i = 2; i <= n; ++i) {
            if (l[i].a * l[i - 1].b == l[i - 1].a * l[i].b) continue;
            l[++siz] = l[i];
        }
        
        if (siz == 1) {
            while (m--) {
                int S, T;
                read(S); read(T);
                if ((i64)S * l[1].b != (i64)T * l[1].a) write("IMPOSSIBLE\n");
                else {
                    char buff[32];
                    sprintf(buff, "%.5f\n", (double)((f80)l[1].c * S / l[1].a));
                    write(buff);
                }
            }
            return 0;
        }
    
        int tp = 2;
        stk[1] = 1; stk[2] = 2;
        p[1] = {0, (f80)l[1].c / l[1].b};
        p[2] = Intersect(l[1], l[2]);
    
        for (int i = 3; i <= siz; ++i) {
            while (tp > 1) {
                if (PointOnLine(l[stk[tp]], Intersect(l[i], l[stk[tp-1]]))) --tp;
                else break;
            }
            p[tp + 1] = Intersect(l[i], l[stk[tp]]);
            stk[++tp] = i;
        }
    
        for (int i = 1; i <= m; ++i) {
            read(q[i].a); read(q[i].b); q[i].id = i;
            ans[i] = INF_MARK; 
        }
        sort(q + 1, q + m + 1, cmp);
    
        int cur = 1;
        for (int i = 1; i <= m; ++i) {
            if (q[i].a * l[1].b > q[i].b * l[1].a) { 
                continue; 
            }
            int pl = stk[tp];
            if (q[i].a * l[pl].b < q[i].b * l[pl].a) break;
            while (cur <= tp) {
                pl = stk[cur];
                if (q[i].a * l[pl].b - q[i].b * l[pl].a >= 0) {
                    ans[q[i].id] = q[i].a * p[cur].first + q[i].b * p[cur].second;
                    break;
                }
                cur++;
            }
        }
    
        for (int i = 1; i <= m; ++i) {
            if (ans[i] > INF_MARK + 1.0) { 
                 char buff[32];
                 sprintf(buff, "%.5f\n", (double)ans[i]);
                 write(buff);
            }
            else write("IMPOSSIBLE\n");
        }
        return 0;
    }
    

    解决思路参考洛谷题解,注意到根据对偶可化作半平面交求解,否则TLE

信息

ID
127
时间
1000ms
内存
256MiB
难度
10
标签
递交数
11
已通过
1
上传者