1 minute read

[no-alignment]

구현 방식

  • 제한 시간이 1초이고 N이 100000 이하의 수 이므로 O(N^2) 이하의 코드를 짜야한다.
  • N개의 용액에서 0번째부터 N-1개까지 순차적으로 하나 선택한 용액 k 와 k+1 ~ N-1 번째까지의 용액 중에 가장 절대값을 최소로 하는 용액을 이분탐색을 통해 찾아낸다.
  • 그렇게 하면 O(N * log (N - k)) 이므로 시간 제한에 걸리지 않을것이다.
  • 여기서 이분탐색할 때, sum == 0 으로 지표를 나누기 때문에 수렴하는 부분이 최소 합을 가지는 게 아닐수도 있다.
  • 최소값을 저장하는 변수를 따로 만들어서 리턴해주자.
#include <iostream>
#include <algorithm>
#include <vector>
#include <limits.h>

using namespace std;

void solution(int N, const vector<long long> &v);
pair<long long, long long> binarySearch(long long number, int minIdx, int maxIdx, const vector<long long> &v);

int main()
{
    int N;
    cin >> N;
    vector<long long> v(N);
    for (int i = 0; i < N; i++) cin >> v[i];

    solution(N, v);
}

void solution(int N, const vector<long long> &v)
{
    long long sumMin = LLONG_MAX;
    pair<long long, long long> result = make_pair(-1, -1);

    for (int i = 0; i < N; i++)
    {
        auto p = binarySearch(v[i], i + 1, N - 1, v);
        auto addNumber = p.first;
        auto sum = abs(p.second);
        if (sumMin > sum)
        {
            result = {v[i], addNumber};
            sumMin = sum;
        }
    }

    cout << result.first << " " << result.second;

}


pair<long long, long long> binarySearch(long long number, int minIdx, int maxIdx, const vector<long long> &v)
{
    long long sumMin = LLONG_MAX;
    pair<long long, long long> result = {-1, sumMin};

    int midIdx = (minIdx + maxIdx) / 2;
    long long sum = LLONG_MAX;
    while (minIdx <= maxIdx)
    {
        midIdx = (minIdx + maxIdx) / 2;
        sum = number + v[midIdx];

        if(sumMin > abs(sum))
        {
            sumMin = abs(sum);
            result = {v[midIdx], sum};
        }

        if (sum == 0) break;
        else if (sum > 0) maxIdx = midIdx - 1;
        else minIdx = midIdx + 1;
    }

    return result;
}