티스토리 뷰

알고리즘/백준

백준 10165 버스 노선

4567은 소수 2022. 8. 16. 23:24

https://www.acmicpc.net/problem/10165

 

10165번: 버스 노선

첫 번째 줄에는 버스 정류소의 개수 N(3 ≤ N ≤ 1,000,000,000)이 주어지고 두 번째 줄에는 버스 노선의 수 M(2 ≤ M ≤ 500,000)이 주어진다. 각 버스 노선은 1부터 M까지의 번호로 구분된다. 그 다음 M개

www.acmicpc.net

원형이라는 조건 때문에 조금 까다로운 문제였습니다.

 

우선 입력으로 들어오는 애들을 a > b 인 경우 b <- b + n 으로 바꿔줍니다. 

 

그리고 전체 입력으로 들어오는 노선 중 길이가 가장 길고 시작점이 짧은 것을 기준으로 정렬시킵니다. (M log M, M 최대 500,000)

이후 순차적으로 앞선 노선과 비교하며 마지막 위치가 포함되는 지 여부를 확인하면 됩니다.

 

시작점은 오름차순, 길이는 내림차순으로 정렬하므로 앞선 노선의 마지막보다 지금의 마지막의 위치가 작다면 무조건 포함되게 됩니다.

 

(새로운 시작점 시 최대 30억까지 갈 수 있는데 int로 해서 한 번 틀렸다... 잔실수를 없애자!)

 

코드는 다음과 같습니다.

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>

using namespace std;

int n, m;
long long a, b;

struct bus {
	long long start;
	long long last;
	long long len;
	int idx;
};

vector<bus> vec;
vector<int> result;

// 가장 긴 애의 시작점을 기준으로 새로운 버스들 만들기
// 시작점 작은 순, 마지막 큰 순으로 정렬하고
// 앞에 거보다 마지막이 작으면 최종적으로 포함 안 시킴 

bool comp(bus& b1, bus& b2) {
	if (b1.start != b2.start)
		return b1.start < b2.start;
	else
		return b1.last > b2.last;
}


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

	cin >> n;
	cin >> m;

	long long max_len = 0;
	int max_idx = 0;
	long long new_start = 0;

	for (int i = 1; i <= m; i++) {
		cin >> a >> b;
		bus B = { a, b, 0, i };

		if (a <= b) {
			B.len = b - a;
		}
		else {
			B.len = n + b - a;
			B.last = n + b;
		}

		vec.push_back(B);

		// 길이 더 긴 거 나타남
		if (B.len > max_len) {
			max_len = B.len;
			max_idx = B.idx;
			new_start = B.start;
		}
		else if (B.len == max_len) {
			// 길이 같으면 시작점 더 작은 거 우선
			// 길이 같고 시작점 같은 거 없음
			if (vec[max_idx - 1].start > B.start) {
				max_len = B.len;
				max_idx = B.idx;
				new_start = B.start;
			}
		}
	}

	// 가장 긴 거의 시작점 기준으로 새로 만들기
	for (int i = 0; i < vec.size(); i++) {
		if (vec[i].start < new_start) {
			vec[i].start = vec[i].start + n;
			vec[i].last = vec[i].last + n;
		}
	}

	// 시작점 빠른 순, 길이 긴 순으로 정렬 
	sort(vec.begin(), vec.end(), comp);

	// 계산 (앞에 거보다 result 마지막이 작으면 포함 안 시킴)
	result.push_back(vec[0].idx);
	long long prev_last = vec[0].last;
	long long now_last = 0;

	for (int i = 1; i < vec.size(); i++) {
		now_last = vec[i].last;
		if (now_last > prev_last) {
			result.push_back(vec[i].idx);
			prev_last = now_last;
		}
	}

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

	for (auto r : result) {
		cout << r << ' ';
	}
}

 

'알고리즘 > 백준' 카테고리의 다른 글

백준 1039 교환  (0) 2022.08.28
백준 9934 완전 이진 트리  (0) 2022.08.28
백준 5582 공통 부분 문자열 C++  (0) 2022.08.12
백준 6487 두 직선의 교차 여부 C++  (0) 2022.08.09
백준 17779 게리멘더링 2 C++  (0) 2022.07.10
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/12   »
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 30 31
글 보관함