https://www.acmicpc.net/problem/2143
시간: 1시간 11분
해결: X
문제
두 정수 배열 A, B의 연속 부분합을 더해서 T와 같은 경우의 수를 구해야 합니다.
저는 문제를 두 개로 나눴습니다.
모든 부분합 구하기
A의 모든 부분합 SA의 크기는 1+2+3+ ... +n이므로 아래와 같습니다.
B의 모든 부분합 SB도 똑같습니다.
부분합 더하기
SA와 SB의 원소를 직접 더 해봅니다.
다만 모든 경우의 수를 전부 구하면 대충 O(n^2*m^2)에 가까워지니 방법이 필요합니다.
제가 시도한 방법은
1. 모든 SA의 원소 a에 대해 합이 T가 되는 SB의 원소 b를 이분 탐색
2. lower_bound()로 a+b=T인 가장 작은 인덱스의 원소를 구하고 하나씩 세기
3. (채택) equal_range()로 SB에서 a+b=T인 b의 개수 구하기
https://velog.io/@cowkjw/C-STL-upperbound-lowerbound-equalrange-binarysearch
[C++ STL] upper_bound, lower_bound, equal_range, binary_search
[C++ STL] 이진 탐색 STL
velog.io
equal_range()에 넘긴 범위는 오름차순으로 정렬 되어있어야 합니다.
코드
const int SZ = 1001;
int n, m;
int A[SZ], B[SZ];
long long T;
vector<long long> SA, SB;
long long solve(){
// vector 메모리 확보
SA.reserve(1LL*n*(n+1)/2);
SB.reserve(1LL*m*(m+1)/2);
// 모든 부분합 구하기
for(int i=0; i<n; i++){
long long sum=0;
for(int j=i; j<n; j++){
sum += A[j];
SA.push_back(sum);
}
}
for(int i=0; i<m; i++){
long long sum=0;
for(int j=i; j<m; j++){
sum += B[j];
SB.push_back(sum);
}
}
// 이분 탐색 위해 정렬
sort(SA.begin(), SA.end());
sort(SB.begin(), SB.end());
long long ret=0;
for(long long a : SA){
long long target = T-a;
auto range = equal_range(SB.begin(), SB.end(), target);
ret += (range.second - range.first);
}
return ret;
}
reserve()는 vector가 사용할 메모리를 미리 할당해줍니다.
vector는 push_back()으로 할당된 메모리보다 크기가 커질 경우, 현재 메모리의 해제하고 그 두 배의 공간을 새로 할당합니다.
이 작업은 최대 O(n)의 시간을 소모하고, 사용할 메모리의 크기를 안다면 reserve()로 사전에 처리하여 시간을 절약할 수 있습니다.
문제에서는 대략 1,000,000개의 원소 공간을 사용하겠네요.
'Coding Test > Baekjoon' 카테고리의 다른 글
| [C++] 백준 11049: 행렬 곱셈 순서 (동적계획법) (0) | 2025.10.12 |
|---|---|
| [C++] 백준 9465: 스티커 (0) | 2025.05.12 |
| [C++] 백준 14500: 테트로미노 (0) | 2025.05.10 |
| [C++] 백준 9019: DSLR (0) | 2025.05.10 |
| [C++] 백준 30804: 과일 탕후루 (0) | 2025.05.01 |