💯Problem Solving
[BOJ] 2568 전깃줄 - 2
date
Aug 5, 2023
slug
boj-2568
author
status
Public
tags
Python
BOJ
summary
백준 0000번 문제풀이입니다.
type
Post
thumbnail
category
💯Problem Solving
updatedAt
Aug 27, 2023 10:40 AM
문제 링크
문제
두 전봇대 A와 B 사이에 하나 둘씩 전깃줄을 추가하다 보니 전깃줄이 서로 교차하는 경우가 발생하였다. 합선의 위험이 있어 이들 중 몇 개의 전깃줄을 없애 전깃줄이 교차하지 않도록 만들려고 한다.
예를 들어, <그림 1>과 같이 전깃줄이 연결되어 있는 경우 A의 1번 위치와 B의 8번 위치를 잇는 전깃줄, A의 3번 위치와 B의 9번 위치를 잇는 전깃줄, A의 4번 위치와 B의 1번 위치를 잇는 전깃줄을 없애면 남아있는 모든 전깃줄이 서로 교차하지 않게 된다.
<그림 1>
전깃줄이 전봇대에 연결되는 위치는 전봇대 위에서부터 차례대로 번호가 매겨진다. 전깃줄의 개수와 전깃줄들이 두 전봇대에 연결되는 위치의 번호가 주어질 때, 남아있는 모든 전깃줄이 서로 교차하지 않게 하기 위해 없애야 하는 최소 개수의 전깃줄을 구하는 프로그램을 작성하시오.
문제풀이
BOJ : 전깃줄 - 1 문제의 LIS의 nlogn 버전
전깃줄 - 1을 풀었고, 가장 긴 증가하는 부분 수열 5를 풀었다면
쉽게 해답을 찾을 수 있다.
문제 해답의 시퀸스는 다음과 같다
- A, B에 해당하는 튜플을 입력받고, B에 대하여 오름차순 정렬을 한다.
- A에 대하여 LIS를 구하고, 역방향 탐색을 통해 LIS sequence를 구해주는 연산을 한다.
- 이떄 LIS sequence가 아닌 것들을 따로 배열에 더해준후, 정렬하여 갯수와 노드의 번호를 출력해주면 된다.
A에 대하여 정렬한후 답을 구해도 거의 비슷한 방법으로 답을 구할 수 있다.

파이썬 문제풀이 코드
import sys import bisect input = sys.stdin.readline N = int(input()) arr = [] for _ in range(N): arr.append(tuple(map(int, input().split()))) # A, B arr.sort(key=lambda x:x[1]) # B를 기준으로 오름차순 정렬 lis = [0] lis_total = [(0, 0)] for item in arr: a, b = item # b는 이미 오름차순되어있음 즉 a만 봐도됨 if lis[-1] < a: # 마지막에 있는 것보다 클경우 그냥 뒤에 붙임 lis.append(a) lis_total.append((len(lis)-1, a)) # 역추적 하기 위한 배열 (idx, value) else: # 마지막에 있는 것보다 작을경우 bisect를 통해서 삽입할 위치를 지정 idx = bisect.bisect_left(lis, a) # a를 어디에 삽입하면 좋을까? lis[idx] = a # 삽입연산 lis_total.append((idx, a)) # 역주적하기 위한 배열 idx와 value pair max_len = len(lis)-1 # lis의 길이 0을 빼줘야함 # debug # print(lis) # print(lis_total) results = [] for item in lis_total[::-1]: idx, value = item if idx == max_len: # 수열을 구하는 문제가 아니므로 패스 max_len-=1 else: results.append(value) # A가 담겨있음 results.sort() # 오름차순이라는 보장은 없기 때문에 정렬 # ans print(len(results)) for value in results: print(value)
시간복잡도
- O(nlogn)
입력
첫째 줄에는 두 전봇대 사이의 전깃줄의 개수가 주어진다. 전깃줄의 개수는 100,000 이하의 자연수이다. 둘째 줄부터 한 줄에 하나씩 전깃줄이 A전봇대와 연결되는 위치의 번호와 B전봇대와 연결되는 위치의 번호가 차례로 주어진다. 위치의 번호는 500,000 이하의 자연수이고, 같은 위치에 두 개 이상의 전깃줄이 연결될 수 없다.
출력
첫째 줄에 남아있는 모든 전깃줄이 서로 교차하지 않게 하기 위해 없애야 하는 전깃줄의 최소 개수를 출력한다. 둘째 줄부터 한 줄에 하나씩 없애야 하는 전깃줄의 A전봇대에 연결되는 위치의 번호를 오름차순으로 출력한다. 만약 답이 두 가지 이상이라면 그 중 하나를 출력한다.
알고리즘 분류
- 구현
- 문자열