핵심은 학번을 키로 하는 해시 테이블을 만들고, 값으로 해당 학번의 최종 상대 순서를 저장하는 것이다.
클릭한 순서를 기록한 대기목록을 한번 순회하면서, index라는 카운터 변수를 한 번의 순회마다 증가시킨다.
1
2
3
4
5
6
7
8
9
10
11
12
// 클릭한 순서를 기록한 대기목록
vector<string> seqs;
// 학번과 최종 상대 순서
unordered_map<string, int> umap;
int index =0;
for (const string& num: seqs) {
++index;
umap[num] = index;
}
이러면 중복된 것이 발견되더라도 항상 마지막 index로 업데이트 되기 때문에, 대기열의 끝으로 보낼 수 있다.
다이어그램으로 표시하면 아래와 같다.
왼쪽 seq의 원소를 하나 하나 순회하면서, umap의 키-값을 업데이트 해 나가면 된다.
이러면 마지막에 umap을 vector로 바꾼 후 정렬을 해 준 후에, 앞에서부터 K개를 출력해 주어야 한다.
복잡도는 클릭 대기열을 한 번 순회하는데 $L$, 정렬에 $L\log{L}$, 앞에서부터 $K$개 출력에 $K$가 드므로, $O(L + L\log{L} + K)$이고, 이는 대략 $O(L\log{L})$이다.
#include<iostream>#include<string>#include<list>#include<unordered_map>#include<vector>usingnamespace std;
int K, L;
vector<string> nums;
unordered_map<string, list<string>::iterator> umap;
list<string> seqs;
intmain() {
cin >> K >> L;
nums.reserve(L);
for (int i =0; i < L; ++i) {
string num; cin >> num;
nums.push_back(num);
}
for (const string& num: nums) {
// 처음 보는 경우
if (umap.find(num) == umap.end()) {
seqs.push_back(num);
umap[num] =--seqs.end();
// 중복되어 보는 경우
} else {
// 위치를 알고 있으므로 지워준다.
seqs.erase(umap[num]);
seqs.push_back(num);
umap[num] =--seqs.end();
}
}
int count =0;
for (const string& num: seqs) {
cout << num <<'\n';
++count;
if (count == K) {
break;
}
}
}