Форум программистов, компьютерный форум, киберфорум
Python для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.66/29: Рейтинг темы: голосов - 29, средняя оценка - 4.66
710 / 356 / 104
Регистрация: 09.02.2018
Сообщений: 805

Количество пересечений отрезков

17.12.2021, 21:14. Показов 5756. Ответов 19
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Привет, задача такая:

На числовой прямой задано несколько отрезков координатами начальной и конечной точек. Требуется подсчитать количество пересекающихся пар отрезков.

Входные данные: первая строка содержит количество отрезков N, далее N строк содержат пары чисел разделенных пробелом - координаты начальной и конечной точек отрезка.

Выходные данные: одно число K - количество пересекающихся пар отрезков.

Пример:

input.txt
Code
1
2
3
4
5
6
7
6
3 5
0 10
4 8
6 8
4 12
9 9
output.txt
Code
1
11
Пояснение:

Отрезок номер 1 пересекается с отрезками 2, 3 и 5.
Отрезок 2 - кроме отрезка номер 1, пересекается еще с отрезками 3, 4, 5 и 6.
Отрезок 3 - пересекается еще с 4 и 5.
Отрезок 4 - пересекается еще с 5.
Отрезок 5 - пересекается еще с 6.

Итого 3 + 4 + 2 + 1 + 1 = 11 пересечений.

Мое наивное решение:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
N, segments = 6, [
    (3, 5),
    (0, 10),
    (4, 8),
    (6, 8),
    (4, 12),
    (9, 9),
]
 
K = 0
for i in range(N):
    for j in range(i + 1, N):
        if segments[i][1] >= segments[j][0]\
        and segments[j][1] >= segments[i][0]:
            K += 1
 
print(K)
Вопрос: как доработать программу для N = 100 000?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
17.12.2021, 21:14
Ответы с готовыми решениями:

Количество пересечений прямоугольника
Дан набор прямоугольников на плоскости со сторонами, параллельными осям координат. Для каждого прямоугольника необходимо вычислить...

Посчитать количество точек пересечений N отрезков плоскости
Посчитать количество точек пересечений N отрезков плоскости.Вводится N(N<=20) каждый отрезок задатся кординатами точек его...

Найти число пересечений отрезков
Положение точки на плоскости задаётся структурой struct POINT{ double x,y; }; Отрезок на плоскости задаётся двумя точками struct...

19
Эксперт Python
8851 / 4502 / 1864
Регистрация: 27.03.2020
Сообщений: 7,317
17.12.2021, 21:42
Лучший ответ Сообщение было отмечено КулХацкеръ как решение

Решение

Может? :
- сортировка по первой координате, затем по второй
- bisect_right второй координаты i-ого отрезка по первым координатам -> количество отрезков минус полученный индекс дает количество непересекающихся отрезков с i-м отрезком
- арифметическая прогрессия от 1 до количества всех отрезков минус сумма всех значений по второму пункту
1
3582 / 2182 / 571
Регистрация: 02.09.2015
Сообщений: 5,510
17.12.2021, 21:50
КулХацкеръ, кури Count number of pairs of lines intersecting at a Point.
0
Status 418
Эксперт Python
4584 / 2350 / 601
Регистрация: 26.11.2017
Сообщений: 5,262
Записей в блоге: 3
17.12.2021, 21:59
сканирующая прямая
0
710 / 356 / 104
Регистрация: 09.02.2018
Сообщений: 805
17.12.2021, 22:22  [ТС]
Gdez,

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from bisect import bisect_right
 
N, segments = 6, [
    (3, 5),
    (0, 10),
    (4, 8),
    (6, 8),
    (4, 12),
    (9, 9),
]
# Сортировка по первой координате, затем по второй.
segments = sorted(segments)
 
# Первые координаты отрезков.
begin_coords = [segment[0] for segment in segments]
 
 
# Количество отрезков, не пересекающихся с отрезком номер i.
def count_not_intersecting_with_i(i):
    end_coord = segments[i][1]
    index = bisect_right(begin_coords, end_coord)
    return N - index
 
 
# Максимальное количество пересечений (если нет непересекающихся отрезков).
# По формуле суммы арифметической прогрессии.
intersects_max = N * (N + 1) // 2
 
print(intersects_max - sum(map(count_not_intersecting_with_i, range(N))))
Ответ получился 17, а должен был быть 11. Что-то промашка в реализации у меня.

Добавлено через 32 секунды
Arsegg, eaa, спасибо за подсказки, буду курить.
0
Эксперт Python
8851 / 4502 / 1864
Регистрация: 27.03.2020
Сообщений: 7,317
17.12.2021, 22:24
КулХацкеръ, в 27-й минус, не плюс
1
710 / 356 / 104
Регистрация: 09.02.2018
Сообщений: 805
17.12.2021, 23:07  [ТС]
Arsegg, это не совсем то, что мне бы хотелось. Меня интересуют не прямые, а отрезки, и эти отрезки лежат на одной прямой, а не на плоскости.

Добавлено через 3 минуты
Gdez, спасибо, ответ для примера из условия верный теперь! Потестирую ещё на других данных и отпишусь.

Добавлено через 36 минут
Все отлично, на других примерах также работает. Спасибо, очень помогли.
1
3750 / 1944 / 612
Регистрация: 21.11.2021
Сообщений: 3,706
18.12.2021, 00:30
Цитата Сообщение от eaa Посмотреть сообщение
сканирующая прямая
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
segments = [
    (3, 5),
    (0, 10),
    (4, 8),
    (6, 8),
    (4, 12),
    (9, 9),]
 
segments.sort()
res = 0
cur_seg_counter = 0
n = segments[0][0]
while segments:
    for seg in segments:
        if seg[0] == n:
            res += cur_seg_counter
            cur_seg_counter += 1
 
    for seg in segments:
        if seg[1] == n:
            segments.remove(seg)
            cur_seg_counter -= 1
    n += 1
print(res)
0
710 / 356 / 104
Регистрация: 09.02.2018
Сообщений: 805
18.12.2021, 01:24  [ТС]
idealist, спасибо, интересный вариант. Правда, по времени не проходит, но посмотрю, можно ли его доработать.
0
3750 / 1944 / 612
Регистрация: 21.11.2021
Сообщений: 3,706
18.12.2021, 04:40
Цитата Сообщение от КулХацкеръ Посмотреть сообщение
Правда, по времени не проходит
А этот:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import bisect
 
segments = [
    (3, 5),
    (0, 10),
    (4, 8),
    (6, 8),
    (4, 12),
    (9, 9), ]
 
segments.sort()
res   = 0
tails = []
for seg in segments:
    while len(tails) and tails[0] < seg[0]:
        tails.pop(0)
    res += len(tails)
    bisect.insort(tails, seg[1])
print(res)
1
710 / 356 / 104
Регистрация: 09.02.2018
Сообщений: 805
18.12.2021, 15:00  [ТС]
Этот вариант лучше, но работает около 6-7 секунд. Алгоритм от Gdez работает за секунду.

Добавлено через 54 секунды
Лимит времени на задачу как раз одна секунда.
0
18.12.2021, 15:07

Не по теме:

КулХацкеръ, попробуй на плюсы переписать.

0
Status 418
Эксперт Python
4584 / 2350 / 601
Регистрация: 26.11.2017
Сообщений: 5,262
Записей в блоге: 3
18.12.2021, 17:42
Pop(0) замени на O(1)
0
3750 / 1944 / 612
Регистрация: 21.11.2021
Сообщений: 3,706
18.12.2021, 18:30
Цитата Сообщение от eaa Посмотреть сообщение
Pop(0) замени на O(1)

Так примерно?:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import bisect
 
segments = [
    (3, 5),
    (0, 10),
    (4, 8),
    (6, 8),
    (4, 12),
    (9, 9), ]
 
segments.sort()
res = 0
tails = []
ind = 0
for seg in segments:
    while ind < len(tails) and tails[ind] < seg[0]:
        ind += 1
    res += len(tails) - ind
    bisect.insort(tails, seg[1])
print(res)
0
710 / 356 / 104
Регистрация: 09.02.2018
Сообщений: 805
19.12.2021, 09:10  [ТС]
idealist, вот что я в итоге вымучил, пытаясь улучшить твоё решение:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import heapq
 
INFINITY = 2111111111
 
segments = [
    (3, 5),
    (0, 10),
    (4, 8),
    (6, 8),
    (4, 12),
    (9, 9), ]
 
segments.sort()
res = 0
tails = [INFINITY]
for seg in segments:
    tail = heapq.heappop(tails)
    while tail < seg[0]:
        tail = heapq.heappop(tails)
    res += len(tails)
    heapq.heappush(tails, tail)
    heapq.heappush(tails, seg[1])
 
print(res)
1
3750 / 1944 / 612
Регистрация: 21.11.2021
Сообщений: 3,706
19.12.2021, 10:28
Лучший ответ Сообщение было отмечено КулХацкеръ как решение

Решение

Цитата Сообщение от КулХацкеръ Посмотреть сообщение
вот что я в итоге
Ну тогда так лучше:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import bisect
import heapq
 
segments = [
    (3, 5),
    (0, 10),
    (4, 8),
    (6, 8),
    (4, 12),
    (9, 9), ]
 
segments.sort()
res   = 0
tails = []
for seg in segments:
    while len(tails) and tails[0] < seg[0]:
        heapq.heappop(tails)
    res += len(tails)
    heapq.heappush(tails, seg[1])
print(res)
1
710 / 356 / 104
Регистрация: 09.02.2018
Сообщений: 805
19.12.2021, 11:21  [ТС]
Да, я написал свой код так потому, что хотел сэкономить на проверке непустоты коллекции, но твой вариант лучше читается.
0
3750 / 1944 / 612
Регистрация: 21.11.2021
Сообщений: 3,706
19.12.2021, 11:37
Цитата Сообщение от КулХацкеръ Посмотреть сообщение
сэкономить на проверке
А по времени проходит этот вариант?

Добавлено через 11 минут
Цитата Сообщение от КулХацкеръ Посмотреть сообщение
хотел сэкономить на проверке непустоты коллекции
Тогда так можно:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import heapq
import math
 
segments = [
    (3, 5),
    (0, 10),
    (4, 8),
    (6, 8),
    (4, 12),
    (9, 9), ]
 
segments.sort()
res   = 0
tails = [math.inf]
heapq.heapify(tails)
for seg in segments:
    while tails[0] < seg[0]:
        heapq.heappop(tails)
    res += len(tails) - 1
    heapq.heappush(tails, seg[1])
print(res)
1
0 / 0 / 0
Регистрация: 21.09.2021
Сообщений: 4
19.12.2021, 11:44
Интересно....
0
710 / 356 / 104
Регистрация: 09.02.2018
Сообщений: 805
19.12.2021, 18:06  [ТС]
Цитата Сообщение от idealist Посмотреть сообщение
А по времени проходит этот вариант?
Да.
Цитата Сообщение от idealist Посмотреть сообщение
Тогда так можно:
Отлично.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
19.12.2021, 18:06
Помогаю со студенческими работами здесь

Задача на нахождение максимального кол-ва пересечений отрезков в точке (оптимизировать алгоритм)
Добрый день! В общем и целом есть задача и звучит она так: Ограничение по времени: 1 секунда Ограничение по памяти: 256 мегабайт На...

Ввести количество отрезков и их длины; найти, сколько треугольников можно составить из этих отрезков
надо написать такую программу: пользователь вводит количество отрезков и их длины, и надо найти сколько треугольников можно составить из...

SQL SELECT посчитать количество пересечений
Есть таблица event_entity, в которой имеются столбцы play_id - идентификатор игры, sport_name - название спорта, home_team и away_team -...

Подсчитать количество точек пересечений прямых
Задано множество прямых на плоскости коэффициентами своих уравнений. Подсчитать количество точек пересечений этих прямых и определить номер...

Получить минимальное количество пересечений диапазонов из таблицы
Имеется таблица с полями id, min, max. Необходимо получить минимальное количество пересечений диапазонов из таблицы. Например: ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Отправка уведомления на почту при изменении наименования справочника
Maks 24.03.2026
Программная отправка письма электронной почты на примере изменения наименования типового справочника "Склады" в конфигурации БП3. Перед реализацией необходимо выполнить настройку системной учетной. . .
модель ЗдравоСохранения 5. Меньше увольнений- больше дохода!
anaschu 24.03.2026
Теперь система здравосохранения уменьшает количество увольнений. 9TO2GP2bpX4 a42b81fb172ffc12ca589c7898261ccb/ https:/ / rutube. ru/ video/ a42b81fb172ffc12ca589c7898261ccb/ Слева синяя линия -. . .
Midnight Chicago Blues
kumehtar 24.03.2026
Такой Midnight Chicago Blues, знаешь?. . Когда вечерние улицы становятся ночными, а ты не можешь уснуть. Ты идёшь в любимый старый бар, и бармен наливает тебе виски. Ты смотришь на пролетающие. . .
Контроль уникальности заводского номера - вариант №2
Maks 24.03.2026
В отличие от предыдущего варианта добавлено прерывание циклов, также добавлены новые переменные для сохранения контекста ошибки перед прерыванием цикла: Процедура ПередЗаписью(Отказ, РежимЗаписи,. . .
SDL3 для Desktop (MinGW): Вывод текста со шрифтом TTF с помощью библиотеки SDL3_ttf на Си и C++
8Observer8 24.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-text-sdl3-c. zip finish-text-sdl3-cpp. zip
Жизнь в неопределённости
kumehtar 23.03.2026
Жизнь — это постоянное существование в неопределённости. Например, даже если у тебя есть список дел, невозможно дойти до точки, где всё окончательно завершено и больше ничего не осталось. В принципе,. . .
Модель здравоСохранения: работники работают быстрее после её введения.
anaschu 23.03.2026
geJalZw1fLo Корпорация до введения программа здравоохранения имела много невыполненных работниками заданий, после введения программы количество заданий выросло. Но на выплатах по больничным это. . .
Контроль уникальности заводского номера - вариант №1
Maks 23.03.2026
Алгоритм контроля уникальности заводского (или серийного) номера на примере нетипового документа выдачи шин для спецтехники с табличной частью, разработанного в конфигурации КА2. Данные берутся из. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru