트리를 만들 때는 트리 높이가 H=logN이고 깊이가 h인 칸엔 노드가 2^h개이고 각 노드가 값 2^(H-h)개를 가지므로
깊이가 h인 칸의 총 값 개수는 h에 상관없이 모두 똑같이 2^h*2^(H-h)=2^H=N개일 것입니다. (편의상 N = 2^H라 가정합시다)
각 칸의 왼쪽/오른쪽 자식의 원소들을 머지소트 하듯이 합쳐서 정렬된 원소를 갖추는 데 선형 시간, 즉 원소 개수의 시간이 걸리므로
층마다 병합에는 총합 O(N)의 시간이 걸리고 층이 logN개이므로 트리를 만드는 데는 실질적으로 O(NlogN)의 시간이 듭니다.
실제로 머지소트를 하는 복잡도와 같죠. 잘은 모르겠지만 트리를 만드는 부분에서는 시간초과가 나진 않으신 것 같구요...
사실 검색하는 부분이 문제입니다. k번째 수를 찾는 연산을 구현하기는 어렵고,
쿼리를 Q'(i, j, x): 구간 [i, j]에서 x보다 작은 수의 개수로 변형시켜서 x를 갖고 이분 탐색을 해서 x보다 작은 수가 k개인 x를 찾아야 합니다.
x보다 작은 수의 개수를 세는 것은 각 노드에서 역시 바이너리서치를 하면 어렵지 않게 구현할 수 있습니다.
시간복잡도는 굉장히 복잡하긴 한데, 각 노드에서 이분탐색을 하는 데 평범한 연산 O(1)보다 큰 O(logN)이 소요되지만
한 번의 쿼리에는 O((logN)^2)가 소모되고 Q' 쿼리 자체도 이분탐색을 해야 하니 log(10^10)번이 곱해져 삼중 로그 시간복잡도가 됩니다.
쿼리가 M개(M<=5000)이므로 O(M*(logN)^2*(log10^10))의 시간이 필요한데 시간 안에 작동이 됩니다.
사실 저도 인터넷에서 다른 고수분들의 글을 보고 구현한 것이고 아마 그분들 중 한 분이 이전 글에 댓글도 다셨던 것 같네요.
http://koosaga.myungwoo.kr/entry/Kth-Number-NEERC-...
제가 참고하였던 글은 이것입니다 ㅋㅋ 여기서 3번 방법을 행하고계신것 맞죠?
sgc109 7년 전
@kks227
이렇게 코드를 작성해봤는데 시간초과가 나옵니다..
트리를 만드는데 O(n^2) 일것같고
검색하는데 총 O(m*n) 아니면 O(m*n*logn) 일것같아서
시간 초과일 것을 예상하긴했는데 애초에 이렇게 하는게 아닌가요?