[Baekjoon, 2143] 두 배열의 합

1 분 소요

두 배열에 대한 모든 부분합을 미리 구한 다음, 한 배열을 정렬하고 이분탐색을 이용하여 답의 갯수를 찾으면 되는 문제이다.

나는 오랜만에 접한 lower_bound(), upper_bound() 함수가 정확히 어떤값을 반환하는지 헷갈렸다. 그래서 정리하고자 이 글을 쓰게되었다.

  • lower_bound(): 찾으려는 값중 제일 첫 인덱스의 이터레이터를 반환한다. 없다면 찾으려는 값보다 큰 값중 가장 작은 값의 이터레이터를 반환한다.
  • upper_bound(): 찾으려는 값보다 큰 값중 가장 작은 값의 이터레이터를 반환한다.

위의 함수를 이용하여 미리 구한 부분합에서 T = subsum1[i] + subsum2[j]를 만족하게 하는 구간의 크기를 모두 더하면 된다.

구현

#include <iostream>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#include <cstring>
#include <stack>
#include <cmath>
#include <climits>
#include <cctype>
using namespace std;

const int MAX = 1000 + 1;

int T, N, M;

vector<long long> calcSubsum(int arr[], int len) {
	vector<long long> ret;
	for (int i = 0; i < len; ++i) {
		long long sum = arr[i];
		ret.push_back(sum);
		for (int j = i + 1; j < len; ++j) {
			sum += arr[j];
			ret.push_back(sum);
		}
	}
	return ret;
}

int main() {
	ios_base::sync_with_stdio(0); cin.tie(0);

	int A[MAX], B[MAX];

	cin >> T;
	cin >> N;
	for (int i = 0; i < N; ++i) {
		cin >> A[i];
	}
	cin >> M;
	for (int i = 0; i < M; ++i) {
		cin >> B[i];
	}

	vector<long long> subsum1 = calcSubsum(A, N);
	vector<long long> subsum2 = calcSubsum(B, M);

	sort(subsum2.begin(), subsum2.end());

	long long ret = 0;
	for (int i = 0; i < subsum1.size(); ++i) {
		int lo = lower_bound(subsum2.begin(), subsum2.end(), T - subsum1[i]) - subsum2.begin();
		int hi = upper_bound(subsum2.begin(), subsum2.end(), T - subsum1[i]) - subsum2.begin();

		ret += hi - lo;
	}

	cout << ret << endl;

	return 0;
}

댓글남기기