## 1) Abridged problem statement

You are given \(N\) line segments in the plane (\(1 \le N \le 300\)), each colored **R**, **G**, or **B**.
Project all points of all segments onto the \(x\)-axis (vertical projection). For each \(x\) on the axis, among all segment points that project to this \(x\), the projected point gets the color of the point **closest to the \(x\)-axis** (i.e., the segment point with minimal \(y\) at that \(x\)).
Compute the total projected lengths on the \(x\)-axis colored **R**, **G**, and **B**. Output each length with precision 0.01.

Given: no two segments share more than one common point.

---

## 2) Detailed editorial (explaining the provided solution)

### Key observation: "winner" only changes at endpoints or intersections
Consider any fixed \(x\). Every (non-vertical) segment that spans this \(x\) contributes exactly one point with that \(x\), with some height \(y(x)\). The color on the projection at \(x\) is determined by the segment with **minimum** \(y(x)\) among those covering \(x\).

Each segment defines a **linear function** \(y(x)\) on its \(x\)-interval \([x_{\min}, x_{\max}]\). The identity of the minimum among a set of lines can only change when:
1. a segment starts/ends (an endpoint \(x\)), or
2. two segments swap order (their graphs intersect), i.e., at an intersection \(x\).

Because the statement guarantees two segments have at most one common point, any pair of (non-parallel) supporting lines intersects at one \(x\), and this can affect ordering at most once.

So if we collect:
- all segment endpoint \(x\)-coordinates, and
- all \(x\)-coordinates of intersections between pairs of segments **within their overlapping \(x\)-ranges**,

then between any two consecutive such \(x\)-values, the set of covering segments is fixed and their relative order by \(y(x)\) is fixed. Therefore, the "winning color" is constant throughout that open interval.

### Strategy
1. **Ignore vertical segments** (where \(x_1 = x_2\)): they project to a single point on the \(x\)-axis, contributing **zero length** to totals.
2. Build an array `xs` of critical \(x\)-coordinates:
   - add each non-vertical segment's \(x\)-endpoints,
   - for every pair of non-vertical segments, compute intersection \(x\) of their supporting lines (if not parallel), and if that \(x\) lies inside the overlap of their \(x\)-intervals, add it.
3. Sort `xs` and unique it with epsilon tolerance.
4. For each consecutive interval \([xs[i], xs[i+1]]\):
   - take `mid = (xs[i] + xs[i+1]) / 2`,
   - among all segments covering `mid`, compute their \(y(\text{mid})\),
   - pick the minimum \(y\) => that segment's color owns the entire interval,
   - add the interval length \((xs[i+1] - xs[i])\) to that color's sum.

### Correctness reasoning
- Since `xs` contains all endpoints and all relevant intersection \(x\)-coordinates, no segment can appear/disappear or swap ordering inside an interval between consecutive `xs`.
- Thus the segment achieving the minimum \(y(x)\) (closest to the axis) is constant throughout that interval, so evaluating at the midpoint is enough.

### Complexity
- Collecting pairwise intersections: \(O(N^2)\).
- Number of critical \(x\)'s is \(O(N^2)\).
- For each interval (also \(O(N^2)\)), scanning all \(N\) segments to find the minimum is \(O(N)\).

Total: **\(O(N^3)\)** worst-case. With \(N \le 300\) this is accepted. The code comments also mention a faster approach (\(O(N^2 \log N)\)) using a Li Chao tree / segment tree with rollback, but it is not implemented.

---

## 3) C++ Solution

```cpp
#include <bits/stdc++.h>
// #include <coding_library/geometry/point.hpp>

using namespace std;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, const pair<T1, T2>& x) {
    return out << x.first << ' ' << x.second;
}

template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& x) {
    return in >> x.first >> x.second;
}

template<typename T>
istream& operator>>(istream& in, vector<T>& a) {
    for(auto& x: a) {
        in >> x;
    }
    return in;
};

template<typename T>
ostream& operator<<(ostream& out, const vector<T>& a) {
    for(auto x: a) {
        out << x << ' ';
    }
    return out;
};

using coord_t = double;

struct Point {
    static constexpr coord_t eps = 1e-9;
    static inline const coord_t PI = acos((coord_t)-1.0);

    coord_t x, y;
    Point(coord_t x = 0, coord_t y = 0) : x(x), y(y) {}

    Point operator+(const Point& p) const { return Point(x + p.x, y + p.y); }
    Point operator-(const Point& p) const { return Point(x - p.x, y - p.y); }
    Point operator*(coord_t c) const { return Point(x * c, y * c); }
    Point operator/(coord_t c) const { return Point(x / c, y / c); }

    coord_t operator*(const Point& p) const { return x * p.x + y * p.y; }
    coord_t operator^(const Point& p) const { return x * p.y - y * p.x; }

    bool operator==(const Point& p) const { return x == p.x && y == p.y; }
    bool operator!=(const Point& p) const { return x != p.x || y != p.y; }
    bool operator<(const Point& p) const {
        return x != p.x ? x < p.x : y < p.y;
    }
    bool operator>(const Point& p) const {
        return x != p.x ? x > p.x : y > p.y;
    }
    bool operator<=(const Point& p) const {
        return x != p.x ? x < p.x : y <= p.y;
    }
    bool operator>=(const Point& p) const {
        return x != p.x ? x > p.x : y >= p.y;
    }

    coord_t norm2() const { return x * x + y * y; }
    coord_t norm() const { return sqrt(norm2()); }
    coord_t angle() const { return atan2(y, x); }

    Point rotate(coord_t a) const {
        return Point(x * cos(a) - y * sin(a), x * sin(a) + y * cos(a));
    }

    Point perp() const { return Point(-y, x); }
    Point unit() const { return *this / norm(); }
    Point normal() const { return perp().unit(); }
    Point project(const Point& p) const {
        return *this * (*this * p) / norm2();
    }
    Point reflect(const Point& p) const {
        return *this * 2 * (*this * p) / norm2() - p;
    }

    friend ostream& operator<<(ostream& os, const Point& p) {
        return os << p.x << ' ' << p.y;
    }
    friend istream& operator>>(istream& is, Point& p) {
        return is >> p.x >> p.y;
    }

    friend int ccw(const Point& a, const Point& b, const Point& c) {
        coord_t v = (b - a) ^ (c - a);
        if(-eps <= v && v <= eps) {
            return 0;
        } else if(v > 0) {
            return 1;
        } else {
            return -1;
        }
    }

    friend bool point_on_segment(
        const Point& a, const Point& b, const Point& p
    ) {
        return ccw(a, b, p) == 0 && p.x >= min(a.x, b.x) - eps &&
               p.x <= max(a.x, b.x) + eps && p.y >= min(a.y, b.y) - eps &&
               p.y <= max(a.y, b.y) + eps;
    }

    friend bool point_in_triangle(
        const Point& a, const Point& b, const Point& c, const Point& p
    ) {
        int d1 = ccw(a, b, p);
        int d2 = ccw(b, c, p);
        int d3 = ccw(c, a, p);
        return (d1 >= 0 && d2 >= 0 && d3 >= 0) ||
               (d1 <= 0 && d2 <= 0 && d3 <= 0);
    }

    friend Point line_line_intersection(
        const Point& a1, const Point& b1, const Point& a2, const Point& b2
    ) {
        return a1 +
               (b1 - a1) * ((a2 - a1) ^ (b2 - a2)) / ((b1 - a1) ^ (b2 - a2));
    }

    friend bool collinear(const Point& a, const Point& b) {
        return abs(a ^ b) < eps;
    }

    friend Point circumcenter(const Point& a, const Point& b, const Point& c) {
        Point mid_ab = (a + b) / 2.0;
        Point mid_ac = (a + c) / 2.0;
        Point perp_ab = (b - a).perp();
        Point perp_ac = (c - a).perp();
        return line_line_intersection(
            mid_ab, mid_ab + perp_ab, mid_ac, mid_ac + perp_ac
        );
    }

    friend coord_t arc_area(
        const Point& center, coord_t r, const Point& p1, const Point& p2
    ) {
        coord_t theta1 = (p1 - center).angle();
        coord_t theta2 = (p2 - center).angle();
        if(theta2 < theta1 - eps) {
            theta2 += 2 * PI;
        }

        coord_t d_theta = theta2 - theta1;
        coord_t cx = center.x, cy = center.y;
        coord_t area = r * cx * (sin(theta2) - sin(theta1)) -
                       r * cy * (cos(theta2) - cos(theta1)) + r * r * d_theta;
        return area / 2.0;
    }

    friend vector<Point> intersect_circles(
        const Point& c1, coord_t r1, const Point& c2, coord_t r2
    ) {
        Point d = c2 - c1;
        coord_t dist = d.norm();

        if(dist > r1 + r2 + eps || dist < abs(r1 - r2) - eps || dist < eps) {
            return {};
        }

        coord_t a = (r1 * r1 - r2 * r2 + dist * dist) / (2 * dist);
        coord_t h_sq = r1 * r1 - a * a;
        if(h_sq < -eps) {
            return {};
        }
        if(h_sq < 0) {
            h_sq = 0;
        }
        coord_t h = sqrt(h_sq);

        Point mid = c1 + d.unit() * a;
        Point perp_dir = d.perp().unit();

        if(h < eps) {
            return {mid};
        }
        return {mid + perp_dir * h, mid - perp_dir * h};
    }

    friend optional<Point> intersect_ray_segment(
        const Point& ray_start, const Point& ray_through, const Point& seg_a,
        const Point& seg_b
    ) {
        Point ray_dir = ray_through - ray_start;
        if(ray_dir.norm2() < Point::eps) {
            return {};
        }
        Point seg_dir = seg_b - seg_a;
        coord_t denom = ray_dir ^ seg_dir;
        if(fabs(denom) < eps) {
            return {};
        }
        coord_t t = ((seg_a - ray_start) ^ seg_dir) / denom;
        if(t < eps) {
            return {};
        }
        coord_t s = ((seg_a - ray_start) ^ ray_dir) / denom;
        if(s < eps || s > 1 - eps) {
            return {};
        }
        return ray_start + ray_dir * t;
    }
};

int n;
vector<pair<Point, Point>> segments;
vector<char> colors;

coord_t y_at(const pair<Point, Point>& seg, coord_t x) {
    auto& [a, b] = seg;
    return a.y + (b.y - a.y) * (x - a.x) / (b.x - a.x);
}

bool covers(const pair<Point, Point>& seg, coord_t x) {
    return x >= seg.first.x - 1e-9 && x <= seg.second.x + 1e-9;
}

void read() {
    cin >> n;
    segments.resize(n);
    colors.resize(n);
    for(int i = 0; i < n; i++) {
        cin >> segments[i].first >> segments[i].second >> colors[i];
        if(segments[i].first.x > segments[i].second.x) {
            swap(segments[i].first, segments[i].second);
        }
    }
}

void solve() {
    // We can first notice that when we project there are at most O(n^2)
    // "maximal" ranges that have the same colour, defined by the X-s of all
    // intersection points and borders of the original segments. So we will
    // start by finding all relevant X values and sorting them. Then in each
    // interval, we want to find the closest line segment and this would be the
    // colour we want. Note that because we consider all intersections, for any
    // point of the segment, the closest segment would be the same. Therefore,
    // an easy approach is that for each of these O(n^2) points we will consider
    // the midpoints m, and then evaluate all segments that "cover" the
    // corresponding range and choose the smallest f(m), where f(m) is the
    // linear function defined by the segment. This can be done with a simple
    // O(n) loop giving us a O(n^3) solution.
    //
    // The O(n^3) solution is enough to pass and this is what we implement, but
    // there is also a way to speed it up to at least O(n^2 log n). We can use
    // a Li Chao or dynamic convex hull. Each line acts as a linear function for
    // a range of X values and we can build a segment tree over the ranges we
    // are interested in, such that each of the n segment splits into at most
    // O(log n) of them. We then do a walk on the tree, and query the state in
    // the leafs. The part we should be careful about is the fact that we need
    // to "undo" the updates, so a persistent Li Chao is a good option. There
    // are at most O(n log n) updates, each in O(log n), and there are O(n^2)
    // leafs which we have to query. This yields a direct O(n^2 log n) bound.

    vector<coord_t> xs;
    for(auto& [a, b]: segments) {
        if(abs(b.x - a.x) < 1e-9) {
            continue;
        }
        xs.push_back(a.x);
        xs.push_back(b.x);
    }

    for(int i = 0; i < n; i++) {
        auto& [ai, bi] = segments[i];
        if(abs(bi.x - ai.x) < 1e-9) {
            continue;
        }
        coord_t si = (bi.y - ai.y) / (bi.x - ai.x);
        coord_t ci = ai.y - si * ai.x;
        for(int j = i + 1; j < n; j++) {
            auto& [aj, bj] = segments[j];
            if(abs(bj.x - aj.x) < 1e-9) {
                continue;
            }
            coord_t sj = (bj.y - aj.y) / (bj.x - aj.x);
            coord_t cj = aj.y - sj * aj.x;
            if(abs(si - sj) < 1e-12) {
                continue;
            }
            coord_t x = (cj - ci) / (si - sj);
            coord_t lo = max(ai.x, aj.x);
            coord_t hi = min(bi.x, bj.x);
            if(x >= lo - 1e-9 && x <= hi + 1e-9) {
                xs.push_back(x);
            }
        }
    }

    sort(xs.begin(), xs.end());
    xs.erase(
        unique(
            xs.begin(), xs.end(),
            [](coord_t a, coord_t b) { return abs(a - b) < 1e-9; }
        ),
        xs.end()
    );

    coord_t sr = 0, sg = 0, sb = 0;

    for(int i = 0; i + 1 < (int)xs.size(); i++) {
        coord_t mid = (xs[i] + xs[i + 1]) / 2.0;
        coord_t len = xs[i + 1] - xs[i];
        coord_t best_y = 1e18;
        char best_color = '?';
        for(int j = 0; j < n; j++) {
            if(abs(segments[j].second.x - segments[j].first.x) < 1e-9) {
                continue;
            }
            if(!covers(segments[j], mid)) {
                continue;
            }
            coord_t y = y_at(segments[j], mid);
            if(y < best_y) {
                best_y = y;
                best_color = colors[j];
            }
        }
        if(best_color == 'R') {
            sr += len;
        } else if(best_color == 'G') {
            sg += len;
        } else if(best_color == 'B') {
            sb += len;
        }
    }

    cout << fixed << setprecision(2);
    cout << "R " << sr << "\n";
    cout << "G " << sg << "\n";
    cout << "B " << sb << "\n";
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int T = 1;
    // cin >> T;
    for(int test = 1; test <= T; test++) {
        read();
        solve();
    }

    return 0;
}
```

---

## 4) Python solution (same approach) with detailed comments

```python
import sys
import math

EPS = 1e-9

def y_at(seg, x):
    """Compute y-value of non-vertical segment at coordinate x."""
    (x1, y1), (x2, y2) = seg
    return y1 + (y2 - y1) * (x - x1) / (x2 - x1)

def covers(seg, x):
    """Check if x lies within segment's x-range (inclusive with epsilon)."""
    (x1, _), (x2, _) = seg
    return x >= x1 - EPS and x <= x2 + EPS

def is_vertical(seg):
    """True if segment is vertical (x1 == x2 within epsilon)."""
    (x1, _), (x2, _) = seg
    return abs(x2 - x1) < EPS

def unique_sorted(xs):
    """Sort xs and remove near-duplicates using EPS tolerance."""
    xs.sort()
    res = []
    for v in xs:
        if not res or abs(v - res[-1]) >= EPS:
            res.append(v)
    return res

def main():
    data = sys.stdin.read().strip().split()
    if not data:
        return
    it = iter(data)
    n = int(next(it))

    segments = []
    colors = []

    # Read segments, normalize so that x1 <= x2 (swap endpoints if needed)
    for _ in range(n):
        x1 = float(next(it)); y1 = float(next(it))
        x2 = float(next(it)); y2 = float(next(it))
        c = next(it)
        if x1 > x2:
            x1, x2 = x2, x1
            y1, y2 = y2, y1
        segments.append(((x1, y1), (x2, y2)))
        colors.append(c)

    xs = []

    # Add endpoints for non-vertical segments
    for seg in segments:
        if is_vertical(seg):
            continue
        (x1, _), (x2, _) = seg
        xs.append(x1)
        xs.append(x2)

    # Add intersection x-coordinates for each pair of non-vertical segments
    for i in range(n):
        seg_i = segments[i]
        if is_vertical(seg_i):
            continue
        (xi1, yi1), (xi2, yi2) = seg_i
        si = (yi2 - yi1) / (xi2 - xi1)          # slope
        ci = yi1 - si * xi1                     # intercept

        for j in range(i + 1, n):
            seg_j = segments[j]
            if is_vertical(seg_j):
                continue
            (xj1, yj1), (xj2, yj2) = seg_j
            sj = (yj2 - yj1) / (xj2 - xj1)
            cj = yj1 - sj * xj1

            # Parallel lines => no single intersection x
            if abs(si - sj) < 1e-12:
                continue

            # Compute intersection x of supporting lines
            x = (cj - ci) / (si - sj)

            # Only keep x if within both segments' x-overlap
            lo = max(xi1, xj1)
            hi = min(xi2, xj2)
            if x >= lo - EPS and x <= hi + EPS:
                xs.append(x)

    xs = unique_sorted(xs)

    sr = sg = sb = 0.0

    # Scan each interval between consecutive critical x's
    for k in range(len(xs) - 1):
        x_left = xs[k]
        x_right = xs[k + 1]
        mid = (x_left + x_right) / 2.0
        length = x_right - x_left

        best_y = 1e100
        best_c = None

        # Find segment with minimal y(mid) among those covering mid
        for seg, c in zip(segments, colors):
            if is_vertical(seg):
                continue
            if not covers(seg, mid):
                continue
            y = y_at(seg, mid)
            if y < best_y:
                best_y = y
                best_c = c

        # Add this interval to the winning color
        if best_c == 'R':
            sr += length
        elif best_c == 'G':
            sg += length
        elif best_c == 'B':
            sb += length
        # If best_c is None, no segment covers mid => contributes nothing

    # Print with 2 digits after decimal point (precision 0.01)
    print(f"R {sr:.2f}")
    print(f"G {sg:.2f}")
    print(f"B {sb:.2f}")

if __name__ == "__main__":
    main()
```

---

## 5) Compressed editorial

- Each non-vertical segment induces a linear function \(y(x)\) on its \(x\)-range.
- The projection color at \(x\) is the color of the segment with **minimal** \(y(x)\) among those covering \(x\).
- This minimum can change only at segment endpoints or at \(x\)-coordinates of intersections of two segments' supporting lines (within their overlapping \(x\)-ranges).
- Collect all such critical \(x\)'s, sort+unique. For each adjacent interval, evaluate all covering segments at the midpoint, pick the smallest \(y\), and add the interval length to that color's total.
- Vertical segments project to a point (zero length) and can be ignored.
- Complexity: \(O(N^2)\) critical points, \(O(N)\) scan per interval → \(O(N^3)\).
