ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 12. 파라메트릭 서치
    SCCC - Soongsil Computing Contest Club/2020 Winter-Study 2020. 2. 10. 15:18
    반응형

    12.md
    0.00MB

    1. 복습
    2. 파라메트릭 서치(이분탐색)

    2805번을 보면,

    f(h) : 높이를 h로 설정해서 자르면 얻는 나무의 양

    이걸 높게 설정할수록 적게 얻고, 많이 설정할수록 많이 얻으니깐 항상 감소하는 모양이 나온다.

    이걸 이진탐색으로 적절한 구간을 찾는다.

    최대값의 최소, 최소값의 최대꼴이면 대부분 파라메트릭 서치를 활용할 수 있다.

    #include <iostream>
    using namespace std;
    typedef long long int ll;
    const int MN = 1000001;
    int T[MN];
    int N, M;
    
    ll f(ll h){
        ll sum=0;
        for(int i=0; i<N; ++i){
            if(T[i] > h) sum+=T[i]-h;
        }
        return sum;
    }
    int main(){
        cin >> N >> M;
        for(int i=0; i<N; ++i){
            cin >> T[i];
        }
    
        int lo = 0, hi = 1e9 + 1;
        //lo는 가능, hi는 불가능.
        while(lo<hi-1){
            ll mid = (lo + hi)/2;
            if(f(mid)>=M) lo = mid;
            else hi=mid;
        }
        cout << lo << '\n';
    }

    연습 : 증가함수일때의 코드 짜보기.

    참고 문제 : 2805, 2512, 1654, 1072

    1. 볼록함수일 때의 파라메트릭 서치(삼분탐색)

    감소하다 증가하는 함수일 때 사용.

    8986번을 보자.

    거리를 고정한다고 하면(삼분탐색으로 거리를 탐색)

    f(x) : 간격을 x로 했을 때, 전봇대들의 이동 거리의 합.

    f(x) = sigma(i=0 ~ N-1)( | i*X - arr[i] | )

    즉, i=0일 때 |X - arr[i]|는 볼록함수이다. (뾰족함)

    i=1일때도 마찬가지

    i=N-1일때도 마찬가지.

    볼록함수는 더해도 항상 볼록함수이기때문에 f(x)는 볼록함수이다.

    기울기는 음수부터 증가하는 증가함수이기 때문에 이웃한 점의 기울기를 기준으로 탐색한다. (뾰족한점때문에 미분이 안되므로 각각 두 점 사이 거리를 구함)

    #include <iostream>
    using namespace std;
    typedef long long int ll;
    int N;
    int arr[100001];
    
    ll f(int X){
        ll sum=0;
        for(int i=0; i<N; ++i){
            sum += abs((ll)i*X - arr[i]);
        }
        return sum;
    }
    
    int main(){
        cin >> N;
        for(int i=0; i<N; ++i){
            cin >> arr[i];
        }
        int lo=1, hi=1000000001;
        while(lo<hi-1) {
            int mid = (lo + hi)/2;
            if(f(mid) - f(mid-1) < 0) lo = mid; // 기울기가 음수일때
            else hi=mid; // 기울기가 양수일 때
        }
        //cout << lo << ' ' << hi << ' ' << f(lo) << ' ' << f(hi) << '\n';
        cout << f(lo) << '\n'; //뾰족한 점의 f()를 출력
    }

    참고로 볼록함수들의 최대도 볼록함수다. 볼록다각형의 겹치는 부분도 볼록다각형이다. 그냥 참고만.

    참고 : 8986, 9998

    반응형

    'SCCC - Soongsil Computing Contest Club > 2020 Winter-Study' 카테고리의 다른 글

    14. 누적 합  (0) 2020.02.10
    13. 분할 정복  (0) 2020.02.10
    11. 유니온 파인드  (0) 2020.02.10
    10. 최단경로, 플로이드-와샬, 다익스트라  (0) 2020.02.10
    9. 그래프, dfs, bfs  (0) 2020.02.10

    댓글

Designed by Tistory.