본문 바로가기
Algorithm(코딩테스트)/코딩테스트 문제 풀이 | 해시,집합(Map,Set)

[백준 19583번] 싸이버개강총회 (C++)

by 카랑현석 2024. 2. 7.

문제

 

문제 분석

- 라이브 스트리밍이 열리고부터 개강총회 시작 전까지 채팅을 친 사람을 1) 이라고 하고,

개강총회가 끝나고부터 라이브 스트리밍이 끝날 때까지 채팅을 친 사람을 2) 이라고 하면,

1)과 2)를 모두 만족하는 사람의 수를 출력하는 문제이다.

 

- 문자열 끼리는 대소비교가 가능하다.

예를 들어 00:30은 01:25 보다 작다.

이를 이용하면 이 문제를 해결할 수 있다.

 

-  1) 에서는 채팅을 친 시간 <= S 이면 set 자료구조에 insert 해주면 된다.

-  2) 에서는 채팅을 친 시간 >= E 이면서 동시에 채팅을 친 시간 <= Q 이고, set 자료구조에 현재 들어있는 (즉, 1)에서 채팅을 쳤던 사람) 인 경우 1), 2)을 만족하는 사람의 수를 한 명 올려주고 set 자료구조에 erase을 해서 중복 카운트가 되지 않도록 해주면 된다. 

이를 아래 정답 코드로 그대로 구현만 하면 된다. 

정답 코드

- key 값의 순서가 상관이 없으므로 unordered_set을 사용한다.

// 1) 개강총회 시작 전에 들어와서 채팅을 친 인원의 이름을 unordered_set에 insert 하고,
// 2) 개강총회가 끝나고나서 스트리밍을 종료하기 전까지 채팅을 친 인원의 이름이 개강총회 시작 전에 들어와서 채팅친 인원 목록에 있으면 unoredered_set에서 erase 하고 인원수(정답)을 +1 한다.

#include <iostream>
#include <unordered_set>

using namespace std;

unordered_set<string> us;

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

	int ans = 0; // 정답
	string S, E, Q;
	cin >> S >> E >> Q;

	while (1) {
		string input_time, name;
		cin >> input_time >> name;
		if (cin.eof() == true) break; // 입력을 받을 때까지 입력받기 

		// 입장 로직
		if (input_time <= S) us.insert(name); // 1)
		
		// 퇴장 로직
		else if (input_time >= E && input_time <= Q) { // 2)
			if (us.find(name) != us.end()) { // 개강총회 시작 전에 채팅을 친 사람인 경우에만 카운트
				us.erase(name);
				ans++;
			}
		}
	}

	cout << ans;

	return 0;
}

 

교훈점

- 중복을 고려(제거) 해야하는 경우 set 자료구조를 고려 해볼만하다.