본문 바로가기
Algorithm/Problem Solving

[BOJ] 13334. 철로

by r4bb1t 2021. 1. 27.
반응형
 

13334번: 철로

입력은 표준입력을 사용한다. 첫 번째 줄에 사람 수를 나타내는 양의 정수 n (1 ≤ n ≤ 100,000)이 주어진다. 다음 n개의 각 줄에 정수 쌍 (hi, oi)가 주어진다. 여기서 hi와 oi는 −100,000,000이상, 100,000,0

www.acmicpc.net

처음 생각했던 풀이는 각 (집, 사무실) 쌍을 시작점 기준으로 정렬한 후 각 쌍을 순회하며 뒤쪽의 끝점들만 따로 정렬한 후 upper_bound로 계산하기...였다. 잘 안 풀리는데다 좋은 풀이도 아닌 것 같아서 매주 일요일마다 진행하는 알고리즘 스터디에 가져갔는데, 이거 우선순위 큐 문제라는 얘기를 듣고 바로 풀이가 생각나서 뚝딱뚝딱 풀었다.

 

struct comp_second
{
    bool operator()(pair<int, int> a, pair<int, int> b)
    {
        if (a.second == b.second)
            return a.first > b.first;
        return a.second > b.second;
    }
};

priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> f;
priority_queue<pair<int, int>, vector<pair<int, int>>, comp_second> s;

 

우선순위 큐를 두 개 만드는데, 하나는 시작점 기준으로, 하나는 끝점 기준으로 오름차순으로 정렬되는 큐이다.

 

cin >> N;
for (int i = 0; i < N; i++)
{
    int p, q;
	cin >> p >> q;
	if (p > q)
		swap(p, q);
	s.push({p, q});
}
cin >> D;
while (!s.empty())
{
	if (s.top().first + D < s.top().second)
	{
		s.pop();
		continue;
	}
	while (!f.empty() && s.top().second > f.top().first + D)
		f.pop();
	f.push(s.top());
	s.pop();
	cnt = max(cnt, (int)f.size());
}
cout << cnt;

 

모든 입력은 끝점 기준 큐 S에 넣고, 시작점 기준 큐 F는 처음에는 비어 있다.

S에서 값을 하나씩 빼서 F에 넣어주는데,  넣었을 때 총 길이가 D가 넘으면 F의 top값들을 총 길이가 D 이하가 될 때까지 뺀다.

이렇게 하면 F에 들어간 쌍들의 총 길이가 D 이하로 유지된다.

각 루프에서의 F의 길이 중 최댓값이 답이다.

 

같이 스터디를 한 친구의 풀이는, 각 쌍이 길이 D 안에 포함되는 철로의 시작점을 부등식으로 만들어서 각 부등식의 시작점과 끝점을 한꺼번에 정렬한 후 결과값에 시작점일 경우에 +1, 끝점일 경우에 -1을 하며 결과값의 최댓값을 구하는 풀이였다.

 

혼자서 고민할 땐 답이 잘 안 나오는데 같이 공부하면 왠지 풀이가 더 잘 떠오르는 느낌이다. 스터디 너무 재밌음.

반응형

'Algorithm > Problem Solving' 카테고리의 다른 글

[BOJ] 10167. 금광  (0) 2021.02.20
[BOJ] 16287. Parcel  (0) 2021.01.27
[BOJ] 6549. 히스토그램에서 가장 큰 직사각형  (0) 2020.05.13
[BOJ] 15678. 연세워터파크  (2) 2020.04.29
[BOJ] 2098. 외판원 순회  (0) 2020.04.17

댓글