문제 링크
✅ PyPy3로 제출했음.
n = int(input())
_list = [[] for _ in range(4)] # [A], [B], [C], [D]가 포함된 리스트
# 각 리스트에 값 넣기
for _ in range(n):
_input = list(map(int, input().split()))
idx = 0
for i in range(4):
_list[i].append(_input[idx])
idx += 1
# A[a] + B[b] + C[c] + D[d] = 0
# A[a] + B[b] = -(C[c] + D[d]) => a와 b의 합, c와 d의 합을 리스트로 변환
ab, cd = [], []
for i in range(n):
for j in range(n):
ab.append(_list[0][i] + _list[1][j])
cd.append(_list[2][i] + _list[3][j])
# 합이 0이 되는 쌍을 찾으려면, 정렬을 해야 한다.
# Why? 합이 0보다 큰지 작은지에 따라 포인터를 움직여야 하는데, 정렬하지 않으면 의미가 없음.(=동작 안함)
ab.sort()
cd.sort()
l, r = 0, len(cd) - 1
cnt = 0 # 총 쌍의 개수
while l < len(ab) and r >= 0:
ab_sum = ab[l]
cd_sum = cd[r]
total_sum = ab_sum + cd_sum # 합
dup_ab, dup_cd = 0, 0
# 합이 0인 쌍이라면
if total_sum == 0:
# 중복되는 수 찾기
while l < len(ab) and ab_sum == ab[l]:
dup_ab += 1
l += 1
while r >= 0 and cd_sum == cd[r]:
dup_cd += 1
r -= 1
cnt += dup_ab * dup_cd # 총 경우의 수 갱신
elif total_sum > 0: # r을 줄여야 한다.
r -= 1
else: # l을 늘려야 한다.
l += 1
print(cnt)
문제의 목표
예전에 풀었던 문제이다. 4개의 포인터를 다루는 방식 말고 다른 것을 사용했다.
로직은 다음과 같다.(전제: (a,b), (c,d)
를 정렬)
(a, b)
, (c, d)
를 묶어서 각 원소들의 합을 리스트로 만든다.l=0, r=len(cd)-1
로 설정하고 투 포인터를 진행한다.(a,b)
, (c,d)
모두에 대해서 찾는다.)(a,b)
, (c,d)
에 대한 개수)를 곱해준다.r
이 너무 크므로 줄인다.l
이 너무 작으므로 늘린다.