코딩테스트

[11663] 선분 위의 점

Patti Smith 2024. 1. 5.
 

11663번: 선분 위의 점

첫째 줄에 점의 개수 N과 선분의 개수 M이 주어진다. (1 ≤ N, M ≤ 100,000) 둘째 줄에는 점의 좌표가 주어진다. 두 점이 같은 좌표를 가지는 경우는 없다. 셋째 줄부터 M개의 줄에는 선분의 시작점과

www.acmicpc.net

 

이분 탐색 문제다.

 

실버 3 문제라 쉽겠다 생각하고 아무 생각 없이 각 선분 마다 해당되는 점을 이분 탐색으로 찾았다가 시간초과가 났다. 당연한 얘기겠지만 제한 시간은 1초인데다 N과 M은 최대 100,000이라 N X M만 해도 1억을 훌쩍 넘긴다. (게다가 N X M X log2였다) 선분의 양 끝 값이 주어진 점보다 작은지 큰지 확인만 하면 되는 문제지만 주어진 점이 선분의 양 끝 값 A, B와 일일이 비교한다면 그런 N X M이 되어 제한 시간을 넘긴다. 따라서 A, B가 주어진 점들의 범위에 있는지 확인할 때 이분 탐색으로 시간을 단축하는 것이 관건이겠다. 나는 그 생각을 못 해서 다른 블로그 글을 참고했다.

 

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

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

	int n, m;

	cin >> n >> m;

	vector<int> dot; // 점
	vector<pair<int, int>> line; // 선분

	for (int i = 0; i < n; i++) {
		int a;
		cin >> a;
		dot.push_back(a);
	}

	for (int i = 0; i < m; i++) {
		int a, b;
		cin >> a >> b;
		line.push_back({a, b});
	}

	sort(dot.begin(), dot.end());

	// 각 선분의 끝 점보다 크거나 작은 점의 index를 가져와 둘의 차이를 구한다.
	for (int i = 0; i < m; i++) {
		int firstIndex = lower_bound(dot.begin(), dot.end(), line[i].first) - dot.begin();
		int lastIndex = upper_bound(dot.begin(), dot.end(), line[i].second) - dot.begin();

		cout << lastIndex - firstIndex << "\n";
	}

}

 

이분 탐색은 c++의 기본 함수인 lower_bound와 upper_bound를 사용했다. 이분 탐색으로 원하는 값 x보다 같거나 작은지, 같거나 큰지 확인하여 해당 index의 값을 return하는 함수다.

 

따라서 이 문제의 관건은

  • 주어진 점들이 이분 탐색될 수 있도록 정렬하는 것.
  • 정렬된 점들 중 A와 B보다 작거나 같거나 커지거나 같아질 때의 index를 구하는 것
  • 구한 index를 가지고 선분 내부에 있는 점들의 개수를 구하면

답을 구할 수 있다.

'코딩테스트' 카테고리의 다른 글

[3079] 입국심사  (1) 2024.01.10
[22871] 징검다리 건너기  (2) 2024.01.09
[1654] 랜선 자르기  (0) 2024.01.07
[2805] 나무 자르기  (1) 2024.01.07
[19637] IF문 좀 대신 써줘  (1) 2024.01.06

댓글