중복 신고 예외 처리를 염두에 두고 분석해보자.

핵심 1: 유저는 서로를 얼마든지 신고를 계속할 수 있다. 단, 중복 신고는 1회만 신고되었음을 확인 (중복 처리 필수)

report의 문법은 [*유저* *신고당하는 유저*] 식의 띄어쓰기가 된 스트링 요소로 입력이 주어진다는 것을 알 수 있다.

핵심 2: k번 신고 스트라이크 제도로 어떤 유저가 정지되었는지 저장하기.

report의 최종합산에 따라서 id_list에서 각각 유저가 다른 유저를 정지시키는데 성공시키면 (k에 해당되는 유저를 신고했다면) 받는 총 메일의 숫자를 result 배열에 저장

핵심 3: 정지된 유저를 신고한 모든 유저에게 메일 발송하기.

코드 풀이

1. 데이터 구조 초기화

unordered_map<string, unordered_set<string>> report_map;
unordered_map<string, int> report_count;
unordered_map<string, int> answer_mail_count;
  • report_map: 특정 사용자가 어떤 사용자들에게 신고당했는지 저장 (unordered_set을 사용해 중복 신고를 방지).
  • report_count: 각 사용자가 신고당한 횟수를 저장.
  • answer_mail_count: 각 사용자가 결과 메일을 몇 번 받았는지 저장.

2. 신고 기록 처리

for (const string& r : report) {
    size_t space = r.find(" ");
    string reporter = r.substr(0, space);
    string reported = r.substr(space + 1);
 
    report_map[reported].insert(reporter);
}
  • 신고 내역을 **report_map**에 저장.
    • 신고자는 reporter, 신고당한 사람은 reported.
    • unordered_set을 사용해 동일 신고자는 1번만 카운트.

3. 신고당한 횟수 계산

for (const auto& entry : report_map) {
    report_count[entry.first] = entry.second.size();
}
  • 각 사용자가 신고당한 횟수를 **report_count**에 저장.
    • entry.first는 신고당한 사용자 ID.
    • entry.second.size()는 신고자를 고유하게 센 횟수.

4. 정지된 사용자 확인 및 메일 수 계산

for (const auto& entry : report_map) {
    const string& reported = entry.first;
    const unordered_set<string>& reporters = entry.second;
 
    if (report_count[reported] >= k) {
        for (const string& reporter : reporters) {
            answer_mail_count[reporter]++;
        }
    }
}
  • 신고당한 횟수가 k 이상인 사용자는 정지.
    • 그 사용자를 신고한 모든 사용자들에게 결과 메일 발송.
    • 결과 메일 수는 **answer_mail_count**에 저장.

5. 결과 배열 생성

for (const string& user : id_list) {
    answer.push_back(answer_mail_count[user]);
}
  • **id_list**의 순서에 따라 결과 메일 수를 벡터로 저장.
    • answer_mail_count에 값이 없으면 기본값(0)이 반환됨.

핵심 포인트

  1. 중복 신고 방지: unordered_set 사용으로 동일 신고를 1회로 처리.
  2. 효율성: unordered_mapunordered_set 사용으로 빠른 조회.
  3. 정지 조건 처리: k를 기준으로 신고당한 사용자 필터링.