백준 2517번 달리기
< 백준 2517번 달리기 - 마포 코딩박 >
사용한 알고리즘: Fenwick tree
선수들이 현재 달리고 있는 순서 대로, 선수들의 능력치가 주어집니다. 능력이 큰 선수는 자신보다 앞에 있는 능력이 작은 선수를 앞지를 가능성이 있습니다. 이때 각 선수의 가능한 최대 등수를 구하는 문제였습니다.
사실 " 각 선수의 가능한 최대 등수 = 들어온 순서 - 자신 앞에 있는 능력 작은 선수 수 " 입니다.
문제풀이는 다음과 같습니다.
(1) (코드: 12~16, 51~59)
선수의 능력이 1~10^9 이므로 이를 그대로 배열로 받을 수 없습니다. ( 터집니다.... )
하지만 선수의 수가 3~5*10^5 밖에 안되므로, 선수들의 능력치를 최대 5*10^5 로 압축했습니다. 즉 선수 능력치가 극단적으로 10, 222222, 99999999999 인 경우나 1, 2, 3 인 경우나 대소는 같습니다.
따라서 저는 능력이 큰 순으로 정렬을 시켜, 가장 큰 값을 5*10^5 부터 차례로 바꾸어 주며 능력을 압축했습니다. ( 선수 수가 최대 5*10^5 입니다. )
(2) (코드: 17~39, 60~68)
들어온 순으로 다시 정렬 시켰습니다. 이후 빨리 들어온 선수부터 보면서 등수를 매겼습니다.
i 번째 선수의 가능한 최대 등수는 i - ( 자신 앞 작은 능력 선수 수 ) 입니다.
i 번째 선수앞에 있는 자신보다 작은 능력의 선수 수를 fenwick tree 로 계산해주었습니다.
사용한 알고리즘: Fenwick tree
선수들이 현재 달리고 있는 순서 대로, 선수들의 능력치가 주어집니다. 능력이 큰 선수는 자신보다 앞에 있는 능력이 작은 선수를 앞지를 가능성이 있습니다. 이때 각 선수의 가능한 최대 등수를 구하는 문제였습니다.
사실 " 각 선수의 가능한 최대 등수 = 들어온 순서 - 자신 앞에 있는 능력 작은 선수 수 " 입니다.
문제풀이는 다음과 같습니다.
(1) (코드: 12~16, 51~59)
선수의 능력이 1~10^9 이므로 이를 그대로 배열로 받을 수 없습니다. ( 터집니다.... )
하지만 선수의 수가 3~5*10^5 밖에 안되므로, 선수들의 능력치를 최대 5*10^5 로 압축했습니다. 즉 선수 능력치가 극단적으로 10, 222222, 99999999999 인 경우나 1, 2, 3 인 경우나 대소는 같습니다.
따라서 저는 능력이 큰 순으로 정렬을 시켜, 가장 큰 값을 5*10^5 부터 차례로 바꾸어 주며 능력을 압축했습니다. ( 선수 수가 최대 5*10^5 입니다. )
(2) (코드: 17~39, 60~68)
들어온 순으로 다시 정렬 시켰습니다. 이후 빨리 들어온 선수부터 보면서 등수를 매겼습니다.
i 번째 선수의 가능한 최대 등수는 i - ( 자신 앞 작은 능력 선수 수 ) 입니다.
i 번째 선수앞에 있는 자신보다 작은 능력의 선수 수를 fenwick tree 로 계산해주었습니다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <utility> | |
#include <vector> | |
#include <algorithm> | |
using namespace std; | |
// 키를 압축해서 , Fenwick tree ~~ | |
// 들어온 순서, 실력 | |
typedef pair<int, int> pii; | |
const int MAX = 500000; | |
int N; | |
vector<pii> V; | |
// 실력 높은순 | |
bool cmp1(const pii &a, const pii &b){ | |
return a.second > b.second; | |
} | |
// 빨리 들어온 순 | |
bool cmp2(const pii &a, const pii &b){ | |
return a.first < b.first; | |
} | |
// Fenwick tree | |
int tree[MAX+1]; | |
int Li(int x){ | |
return x&(-x); | |
} | |
int sum(int x){ | |
int ret = 0; | |
while(x>0){ | |
ret += tree[x]; | |
x-=Li(x); | |
} | |
return ret; | |
} | |
void update(int x){ | |
while(x<=MAX){ | |
tree[x]++; | |
x+=Li(x); | |
} | |
} | |
int main(){ios::sync_with_stdio(false);cout.tie(NULL);cin.tie(NULL); | |
#ifndef ONLINE_JUDGE | |
freopen("input.txt", "r", stdin); | |
#endif | |
cin >> N; | |
for (int i = 1; i <= N; ++i){ | |
int ability; | |
cin >> ability; | |
V.push_back(pii(i,ability)); | |
} | |
// 능력 큰순으로 정렬 | |
sort(V.begin(),V.end(),cmp1); | |
// N이 최대 500000 이므로 능력을 압축해준다. | |
// 예를들어 능력이 각각 100 15 1 인 거나 3 2 1 이나 대소는 똑같다. | |
int Abil = MAX+1; | |
for (int i = 0; i < N; ++i){ | |
V[i].second = Abil; | |
Abil--; | |
} | |
sort(V.begin(),V.end(),cmp2); | |
// 들어온 순서대로 보면서, 이전에 자신보다 능력이 낮은 사람이 몇명 왔나 센다. | |
// 등수 = 들어온 순서 - 자신보다 낮은 능력 사람 수 | |
for(auto now: V){ | |
// now.second : now.first 번째 사람의 능력치 | |
cout << now.first- sum(now.second) << '\n'; | |
update(now.second); | |
} | |
return 0; | |
} |
댓글
댓글 쓰기
긴 글 읽어주셔서 감사합니다.
궁금한게 있으시다면 댓글 달아주세요!