Coding Test/Solution

[C++] 1209 - 단조수열 만들기 (플래티넘4)

나죽못고나강뿐 2022. 9. 3. 12:40

1. 문제 설명

 

 

1209번: 단조수열 만들기

음이 아닌 정수로 이루어진 수열 $A_1, A_2, \dots , A_N$이 있다. 단조수열 $B_1, B_2, \dots , B_N$을 만들어서 $|A_1-B_1| + |A_2-B_2| + \dots + |A_N-B_N|$을 최소로 하는 프로그램을 작성하시오. 단조수열이란 $B_1≤B

www.acmicpc.net

로직은 극단적으로 쉬우나 수학이 문제다..


2. 아이디어

 

 

BOJ 1209 단조수열 만들기 : O(NlgN)

https://www.acmicpc.net/problem/1209 최근 CF에 똑같은 문제가 출제되었는데, 짱짱맨 분들이 O(nlgn)에 풀어주신 덕분에 오랜 난제(http://koosaga.myungwoo.kr/110) 가 해결됐다. http://codeforces.com/blog/e..

koosaga.com

내 처음 아이디어는 이게 아니긴 했지만, 훨씬 깔끔한 코드가 있길래 기억 조작해서 이 코드로 풀었다고 하련다.

얼추 뭐 흐름은 같으니까! 🤪🤪🤪

농담이고 내가 작성한 코드도 다시 다듬어서 시도해보자..대충 문제의 본질은 파악했었는데 왜 안 되는 지 모르겠다.

수학적인 내용은 위 블로그에서 참고하면 된다.

 

우선 순위 큐를 써서 단조 수열을 만들자는 건데 쉬운 내용은 아니다.

참고로 위의 블로그에서는 초기값을 2억으로 잡았는데, 16년도 자료라 그 뒤로 데이터가 추가됐는지

그대로는 통과할 수가 없다.

아무래도 최악의 경우의 수를 고려하면 적어도 200 * 100,000,000 정도로는 초기화해야 한다. 

 


3. 코드

#include <iostream>
#include <queue>
#include <algorithm>

#define ll long long
#define endl '\n'

using namespace std;

int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    
    int N; cin >> N;
    ll ret = 2001e9;
    ll arr[2010];
    for (int i=0; i<N; i++) cin >> arr[i];

    for (int i=0; i<2; i++) {
        priority_queue<int> q;
        ll tmp = 0;
        for (int j=0; j<N; j++) {
            if (!q.empty() && q.top() > arr[j]) {
                tmp += q.top() - arr[j];
                q.pop();
                q.push(arr[j]);
            }
            q.push(arr[j]);
        }
        ret = min(ret, tmp);
        reverse(arr, arr+N);
    }
    cout << ret << endl;
    return 0;
}