задача:
Вася нарисовал n секторов на плоскости. Найдите площадь их объединения.

Входные данные

В входных данных находится ноль или более тестов, заканчивающихся концом файла. В первой строке каждого теста находится число число n - количество секторов, нарисованных Васей (1≤n≤500). Следующие n строк содержат 5 чисел: xi, yi, ri, si и αi, где (xi,yi) - центр круга, ri - его радиус, si - угол начала сектора в радианах (измеряется против часовой стрелки, начиная от оси OX), а αi - угол, образующий сектор. xi, yi, ri - целые числа (−100≤xi,yi≤100, 1≤ri≤100), s_i и ai - действительные числа, заданные с точностью до трех знаков после запятой (0≤si,αi≤6). Гарантируется, что сумма всех n не превосходит 500.

Выходные данные

Для каждого теста выведите ответ на задачу. Ответ будет принят системой, если абсолютная или относительная погрешность не превосходит 10^-6.

моё решение:

#include <bits/stdc++.h>
using namespace std;

const long double PI = acosl(-1.0L);
const long double EPS = 1e-12;

// Структура для сектора
struct Sector {
    long double x_coord, y_coord;
    long double radius;
    long double start_angle;
    long double angle; 
};

// Функция проверки близких значений с учетом EPS
bool are_close(long double a, long double b) {
    return fabsl(a - b) < EPS;
}

// Структура для событий по оси X
struct Event {
    long double x;
    int type; // 1 = добавление сектора, -1 = удаление сектора
    int sector_id;
    bool operator<(const Event& other) const {
        if (!are_close(x, other.x)) return x < other.x;
        return type < other.type; // Добавление перед удалением
    }
};

// Нормализация угла в диапазон [0, 2π)
long double normalize_angle(long double alpha) {
    alpha = fmod(alpha, 2.0L * PI);
    if (alpha < 0) {
        alpha += 2.0L * PI;
    }
    return alpha;
}

// Проверка, находится ли угол alpha внутри сектора [start, start + extent)
bool is_angle_between(long double alpha, long double start, long double extent) {
    alpha = normalize_angle(alpha);
    start = normalize_angle(start);
    long double end = normalize_angle(start + extent);

    if (extent >= 2.0L * PI - EPS) {
        return true;
    }

    if (start < end) {
        return (alpha >= start - EPS && alpha < end - EPS);
    } else { 
        return (alpha >= start - EPS || alpha < end - EPS);
    }
}

// Объединение перекрывающихся Y-интервалов
vector<pair<long double, long double>> merge_intervals(vector<pair<long double, long double>>& intervals) {
    vector<pair<long double, long double>> merged;
    if (intervals.empty()) {
        return merged;
    }

    // Сортировка интервалов по началу
    sort(intervals.begin(), intervals.end());

    long double current_start = intervals[0].first;
    long double current_end = intervals[0].second;

    for (size_t i = 1; i < intervals.size(); i++) {
        if(intervals[i].first <= current_end + EPS) {
            current_end = max(current_end, intervals[i].second);
        } else {
            merged.emplace_back(current_start, current_end);
            current_start = intervals[i].first;
            current_end = intervals[i].second;
        }
    }
    merged.emplace_back(current_start, current_end);

    return merged;
}

// Получение Y-диапазонов, покрытых сектором на заданной координате X
vector<pair<long double, long double>> get_sector_y_coverage(const Sector& sector, long double x) {
    vector<pair<long double, long double>> intervals;

    long double dx = x - sector.x_coord;

    if (fabsl(dx) > sector.radius + EPS) {
        return intervals;
    }

    long double dy_sq = sector.radius * sector.radius - dx * dx;
    if (dy_sq < -EPS) {
        return intervals;
    }

    long double dy = (dy_sq < 0.0L) ? 0.0L : sqrtl(dy_sq);

    long double y_min_circle = sector.y_coord - dy;
    long double y_max_circle = sector.y_coord + dy;

    if (sector.angle >= 2.0L * PI - EPS) {
        intervals.emplace_back(y_min_circle, y_max_circle);
        return intervals;
    }

    long double alpha_start = normalize_angle(sector.start_angle);
    long double alpha_end = normalize_angle(sector.start_angle + sector.angle);

    long double alpha_top = PI / 2.0L;
    long double alpha_bottom = 3.0L * PI / 2.0L;

    vector<long double> y_intersections;

    if (fabsl(dx) > EPS) {
        if (fabsl(cosl(alpha_start)) >= EPS) {
            long double y_start = sector.y_coord + dx * tanl(alpha_start);
            if (y_start >= y_min_circle - EPS && y_start <= y_max_circle + EPS) {
                y_intersections.emplace_back(y_start);
            }
        }

        if (fabsl(cosl(alpha_end)) >= EPS) {
            long double y_end = sector.y_coord + dx * tanl(alpha_end);
            if (y_end >= y_min_circle - EPS && y_end <= y_max_circle + EPS) {
                y_intersections.emplace_back(y_end);
            }
        }
    } else {
        // Особая обработка для dx = 0
        bool includes_upper = is_angle_between(alpha_top, alpha_start, sector.angle);
        bool includes_lower = is_angle_between(alpha_bottom, alpha_start, sector.angle);

        if (includes_upper && includes_lower) {
            intervals.emplace_back(y_min_circle, y_max_circle);
            return intervals;
        } else if (includes_upper) {
            intervals.emplace_back(sector.y_coord, y_max_circle);
            return intervals;
        } else if (includes_lower) {
            intervals.emplace_back(y_min_circle, sector.y_coord);
            return intervals;
        }
        // Если ни одно направление не включено, не добавляем покрытие
        return intervals;
    }

    y_intersections.emplace_back(y_min_circle);
    y_intersections.emplace_back(y_max_circle);

    // Удаляем дубликаты и сортируем
    sort(y_intersections.begin(), y_intersections.end());
    y_intersections.erase(unique(y_intersections.begin(), y_intersections.end(),
        [&](long double a, long double b) -> bool {
            return fabsl(a - b) < EPS;
        }), y_intersections.end());

    // Создаем интервалы между пересечениями и проверяем, находятся ли они внутри сектора
    for (size_t i = 0; i + 1 < y_intersections.size(); ++i) {
        long double y1 = y_intersections[i];
        long double y2 = y_intersections[i + 1];
        long double ym = (y1 + y2) / 2.0L;

        long double alpha = atan2l(ym - sector.y_coord, dx);
        if (alpha < 0.0L) {
            alpha += 2.0L * PI;
        }

        if (is_angle_between(alpha, alpha_start, sector.angle)) {
            y1 = max(y1, y_min_circle);
            y2 = min(y2, y_max_circle);
            if (y1 < y2 - EPS) { // Проверка, что интервал имеет ненулевую длину
                intervals.emplace_back(y1, y2);
            }
        }
    }

    return intervals;
}

// Вычисление покрытия по Y на заданной координате X с учетом активных секторов
long double coverage_at_x(const vector<Sector>& active_sectors, long double x) {
    vector<pair<long double, long double>> y_coverage;
    for (const auto &sector : active_sectors) {
        auto intervals = get_sector_y_coverage(sector, x);
        for (auto &interval : intervals) {
            y_coverage.emplace_back(interval.first, interval.second);
        }
    }
    if (y_coverage.empty()) {
        return 0.0L;
    }

    auto merged = merge_intervals(y_coverage);
    long double coverage = 0.0L;
    for (auto &interval : merged) {
        coverage += (interval.second - interval.first);
    }
    return coverage;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    int n;
    // Вывод с высокой точностью
    cout << fixed << setprecision(12);

    while (cin >> n) {
        vector<Sector> sectors(n);
        vector<Event> events;

        for (int i = 0; i < n; i++) {
            cin >> sectors[i].x_coord >> sectors[i].y_coord >> sectors[i].radius 
                >> sectors[i].start_angle >> sectors[i].angle;

            // Добавляем события для начала и конца сектора
            long double x_min = sectors[i].x_coord - sectors[i].radius;
            long double x_max = sectors[i].x_coord + sectors[i].radius;
            events.push_back(Event{x_min, 1, i});
            events.push_back(Event{x_max, -1, i});

            // Проекции начального и конечного углов сектора на ось X
            long double alpha_start = normalize_angle(sectors[i].start_angle);
            long double alpha_end = normalize_angle(sectors[i].start_angle + sectors[i].angle);

            // Если cos(alpha_start) не близко к нулю, добавляем x-проекцию
            if (fabsl(cosl(alpha_start)) >= EPS) {
                long double x_proj_start = sectors[i].x_coord + sectors[i].radius * cosl(alpha_start);
                events.push_back(Event{x_proj_start, 0, i});
            }

            // То же самое для alpha_end
            if (fabsl(cosl(alpha_end)) >= EPS) {
                long double x_proj_end = sectors[i].x_coord + sectors[i].radius * cosl(alpha_end);
                events.push_back(Event{x_proj_end, 0, i});
            }
        }

        // Сортировка событий
        sort(events.begin(), events.end());

        // Plane Sweep
        vector<int> active_ids; // ID активных секторов
        long double last_x = -1e18L;
        long double total_area = 0.0L;

        for (const auto &event : events) {
            long double current_x = event.x;

            if (last_x < current_x - EPS) {
                // Активные секторы
                vector<Sector> active_sectors;
                for(auto id : active_ids){
                    active_sectors.push_back(sectors[id]);
                }

                // Разбиение полосы [last_x, current_x] на k под-полос
                int k = 100; // Количество под-полос на каждую полосу
                long double dx_total = current_x - last_x;
                long double h = dx_total / k;

                for(int j=0; j<k; j++){
                    long double sub_left = last_x + j * h;
                    long double sub_right = sub_left + h;
                    long double sub_mid = (sub_left + sub_right) / 2.0L;

                    // Вычисляем покрытие в точках sub_left, sub_mid, sub_right
                    long double coverage_left = coverage_at_x(active_sectors, sub_left);
                    long double coverage_mid = coverage_at_x(active_sectors, sub_mid);
                    long double coverage_right = coverage_at_x(active_sectors, sub_right);

                    // Метод Симпсона
                    long double area_interval = (coverage_left + 4.0L * coverage_mid + coverage_right) / 6.0L * h;
                    total_area += area_interval;
                }
            }

            // Обработка события
            if (event.type == 1) {
                active_ids.push_back(event.sector_id);
            }
            else if (event.type == -1) {
                // Удаление сектора из active_ids
                // Используем поиск и удаление
                auto it = find(active_ids.begin(), active_ids.end(), event.sector_id);
                if(it != active_ids.end()){
                    active_ids.erase(it);
                }
            }
            // type ==0 игнорируем (только для критических x-проекций)

            last_x = current_x;
        }

        // Необходимо обработать оставшуюся область после последнего события, если она есть
        // Обычно должно быть закрыто, но дополним на всякий случай
        // Но исходные данные предполагают, что все области закрыты

        // Вывод результата
        cout << total_area << "\n";
    }
}

как я могу улучшить мой код, чтоб ответ был более точным?