문제
문제 분석
- 라이브 스트리밍이 열리고부터 개강총회 시작 전까지 채팅을 친 사람을 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 자료구조를 고려 해볼만하다.