포스트

Pr.

Pr.2910 빈도정렬

문제

회전판에 먹어야 할 N 개의 음식이 있다. 각 음식에는 1부터 N 까지 번호가 붙어있으며, 각 음식을 섭취하는데 일정 시간이 소요된다. 무지는 다음과 같은 방법으로 음식을 섭취한다.

  • 무지는 1번 음식부터 먹기 시작하며, 회전판은 번호가 증가하는 순서대로 음식을 무지 앞으로 가져다 놓는다.
  • 마지막 번호의 음식을 섭취한 후에는 회전판에 의해 다시 1번 음식이 무지 앞으로 온다.
  • 무지는 음식 하나를 1초 동안 섭취한 후 남은 음식은 그대로 두고, 다음 음식을 섭취한다.
    • 다음 음식이란, 아직 남은 음식 중 다음으로 섭취해야 할 가장 가까운 번호의 음식을 말한다.
  • 회전판이 다음 음식을 무지 앞으로 가져오는데 걸리는 시간은 없다고 가정한다. 무지가 먹방을 시작한 지 K 초 후에 네트워크 장애로 인해 방송이 잠시 중단되었다. 무지는 네트워크 정상화 후 다시 방송을 이어갈 때, 몇 번 음식부터 섭취해야 하는지를 알고자 한다. 각 음식을 모두 먹는데 필요한 시간이 담겨있는 배열 food_times, 네트워크 장애가 발생한 시간 K 초가 매개변수로 주어질 때 몇 번 음식부터 다시 섭취하면 되는지 return 하도록 solution 함수를 완성하라.

    입력

  • food_times 는 각 음식을 모두 먹는데 필요한 시간이 음식의 번호 순서대로 들어있는 배열이다.
  • k 는 방송이 중단된 시간을 나타낸다.
  • 만약 더 섭취해야 할 음식이 없다면 -1을 반환하면 된다.

출력

첫째 줄에 입력으로 주어진 수열을 빈도 정렬한 다음 출력한다.

예제 입력

1

예제 출력

1

풀이과정

전제조건

  1. 시간 복잡도, 공간 복잡도
    • 시간복잡도 : 효율성테스트 기준 food_times : 20만, k : 2 * 10^13
    • 단순 구현으로 접근 하면 시간 복잡도는 20만 * 2 * 10^13 으로 시간 초과(1억 번 연산 이상) 발생
  2. 최대, 최소 조건
    • k는 1 이상 2 x 10^13 이하의 자연수이다.
    • food_times 의 길이는 1 이상 200,000 이하이다.
    • food_times 의 원소는 1 이상 100,000,000 이하의 자연수이다.
  3. 사용 알고리즘
    • logN이 걸리는 자료구조로 문제 해결(map, tree, 우선순위 큐)
    • 2개의 기준(음식시간, 음식순번)이 필요함 -> map, 우선순위 큐
    • 가장 빨리 먹는 음식(시간이 가장 짧은)기준으로 회전 -> 그리디 알고리즘
    • 한바퀴 돌았을때 k에 도달 여부 확인 후 반복 -> 음식시간 기준 정렬
    • k에 근접햇을대 순번 기준으로 음식 탐색 -> 음식순번 기준 정렬
    • 우선순위큐를 적용한 그리디 알고리즘으로 접근
  4. 반례, 경계값
    • 먹을 음식이 없으면 -1 반환

제출 코드

  • 답안 참고

해설

생각해볼 점

  • map의 자료구조 성질을 이해하자

정답 코드

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
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
int a[1004];
vector<pair<int,int>> v;
map<int,int> mp, mp_first;

bool cmp(pair<int,int> a, pair<int, int> b){
  if(a.first == b.first){
    return mp_first[a.second] < mp_first[b.second];
  }
  return a.first > b.first;
}


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

  int n,c;
  cin >> n >> c;
  for (int i =0; i < n; i++){
    cin >> a[i];
    mp[a[i]]++;
    if(mp_first[a[i]] == 0) mp_first[a[i]] = i + 1;
  }

  for(auto it :mp){
    v.push_back({it.second, it.first});
  }

  sort(v.begin(), v.end(), cmp);

	for(auto i : v){
		for(int j = 0; j < i.first; j++){
			cout << i.second << " ";
		}
	} 

  
  return 0;
}
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.