👉 문제바로가기
T: 테스트 케이스의 갯수
N, M: 각각 A의 수와 B의 수를 의미 (1 ≤ N, M ≤ 20,000)
각 테스트케이스 마다 A를 리스트에 저장하고, B를 리스트에 저장합니다. i, j가 각각 A리스트와 B리스트의 인덱스라고 할 때 우리가 구해야 하는 것은 A[i] > B[j]를 만족하는 i, j쌍의 갯수입니다.
처음 문제를 보면 단순히 A와 B의 요소를 모두 탐색하여 비교하는 방법을 생각할 수 있으나 코딩 문제풀이에서는 시간복잡도를 고려해보아야 합니다. 모든 요소를 탐색할 경우 i, j에 대한 이중 for문을 사용할 수 있는데 이때 최악의 경우 (20,000)^2 = 400,000,000번의 연산이 수행되며 이는 1초동안 수행될 수 없는 연산 횟수입니다. 따라서 미리 정렬시킨 후 A의 원소보다 B의 원소가 크면 해당되는 B의 원소보다 더 큰 인덱스를 가진 원소는 비교할 필요가 없는것이죠. 이렇게 필요하지 않은 반복을 줄이면 되겠습니다.
N, M의 크기가 작지 않기 때문에 이진 탐색을 생각해볼 수 있습니다. 이진 탐색으로 각 리스트의 원소를 비교한 후 비교를 하지 않아도 되는 원소를 굳이 반복해서 탐색하지 않는 경우 효율적이겠네요.
A리스트 각각의 요소들에 대해 B리스트 요소를 이진 탐색하면 시간복잡도는 O(logM)입니다. 여기서 A원소 는 총 N개이므로 총 시간복잡도는 O(NlogM)이 되겠네요. 따라서 약 180,000회의 연산이 필요할 것이고 이는 1초안에 충분히 가능한 연산 횟수입니다.
count를 1씩 증가시킵니다.count를 출력합니다.import sys
T = int(sys.stdin.readline())
def search(array, target, start, end):
result = -1
while start <= end:
mid = (start + end) // 2
if array[mid] < target:
result = mid
start = mid + 1
else:
end = mid - 1
return result
for _ in range(T):
A, B = map(int, sys.stdin.readline().split())
arrA = list(map(int, sys.stdin.readline().split()))
arrB = list(map(int, sys.stdin.readline().split()))
arrA.sort()
arrB.sort()
count = 0
for i in range(A):
count += (search(arrB, arrA[i], 0, B-1)+1)
print(count)
bisect라이브러리를 활용하면 더 간단하게 해결할 수 있습니다.
import sys
import bisect
T = int(sys.stdin.readline())
for _ in range(T):
A, B = map(int, sys.stdin.readline().split())
arrA = list(map(int, sys.stdin.readline().split()))
arrB = list(map(int, sys.stdin.readline().split()))
arrA.sort()
arrB.sort()
count = 0
for i in range(A):
count += bisect.bisect(arrB, arrA[i]-1)
print(count)
bisect라이브러리