백준: Silver4① - 1015, 1021, 1026, 1049

2 분 소요


</br> 실버 4 문제들~
</br>

1015: 수열 정렬

https://www.acmicpc.net/problem/1015

처음에 문제가 이해 안 됐었는데, 쉽게 말하면 입력된 수열 A의 각 원소가 A에서 몇 번째로 큰지가 출력 수열 P다.

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

    map<int, int> m, mm;
    for(int i = 0; i < n; i++){
        auto ret = m.insert(pair<int, int>(v2[i], i));
        if( ret.second == false ){
            auto ret = m.insert(pair<int, int>(v2[i], 1));
            if( ret.second == false ){
                mm[v2[i]]++;
            }
        }
    }

    for(int i = 0; i < n; i++){
        if( mm.find(v[i]) != mm.end() ){
            cout << m[v[i]]++ << ' ';
            mm[v[i]]--;
            if( mm[v[i]] < 0 ){
                mm.erase(v[i]);
                m.erase(v[i]);
            }
        }
        else{
            cout << m[v[i]] << ' ';
            m.erase(v[i]);
        }
    }

A에 같은 게 있다면 사전 순으로 작은 것을 우선해서 출력해야 한다.
…는 조건에 집착해서 무지성으로 맵으로 풀었는데 너무 복잡한 것 같다.

이건 다른 사람들 코드 찾아 봐야겠다.
</br>

1021: 회전하는 큐

https://www.acmicpc.net/problem/1094

큐를 좌우로 이동시키거나 뽑아내기 완전 덱이랑 똑같음!!

    deque<int> dq;

    for(int i = 1; i < n+1; i++){
        dq.push_back(i);
    }

    int cnt = 0;

    for(int i = 0; i < k; i++){
        int a;
        cin >> a;
        for(int j = 0; j < n; j++){
            if( dq[j] == a ){
                if( n == 1 ){
                    break;
                }
                if( j == 0 ){
                    dq.pop_front();
                }
                else if( j == n-1 ){
                    cnt++;
                    dq.pop_back();
                }
                else if( j < n - j ){
                    cnt += j;
                    for(int k = 0; k < j; k++){
                        dq.push_back(dq.front());
                        dq.pop_front();
                    }
                    dq.pop_front();
                }
                else{
                    cnt += n - j;
                    for(int k = 0; k < n - j - 1; k++){
                        dq.push_front(dq.back());
                        dq.pop_back();
                    }
                    dq.pop_back();
                }
                n--;
                break;
            }
        }
    }

덱에서 원소를 찾고, 좌우 중에 가까운 쪽을 골라 넘겨 주고 뽑아낸다.

덱에 원소가 하나 남았다면 연산 횟수 더할 것 없이 바로 걔를 뽑아낸다.
맨 앞에서 발견해도 연산 횟수를 더하지 않고 바로 빼준다.
맨 뒤에서 발견하면 왼쪽으로 옮겨 줘야 하니 한 번 더하고 빼준다.
왼쪽에 가까운 곳에서 발견하면 앞에 있는 원소들을 다 뒤로 옮겨 주고 빼낸다. 연산 횟수는 j번 오른쪽에 가까운 곳에서 발견하면 뒤에 있는 원소들을 다 앞으로 옮겨 주고 빼낸다. 연산 횟수는 n-j번
</br>

1026: 보물

https://www.acmicpc.net/problem/1026

각 배열의 같은 인덱스 원소끼리 곱해서 가장 작은 합 만들기
A의 순서를 바꿀 수 있다.

    priority_queue<int, vector<int>, greater<int>> a;
    priority_queue<int, vector<int>, less<int>> b;
    int n;

    cin >> n;
    for(int i = 0; i < n; i++){
        int k;
        cin >> k;
        a.push(k);
    }
    for(int i = 0; i < n; i++){
        int k;
        cin >> k;
        b.push(k);
    }

    int s = 0;
    while(a.size()){
        s += a.top() * b.top();
        a.pop(); b.pop();
    }

B는 재배열하면 안 된다는데 왜 저런 의미없는 조건이… 어차피 B의 가장 큰 수를 A의 가장 작은 수와 곱해야 합이 작아지므로,

그냥 A 배열은 오름차순 우선순위 큐에, B 배열은 내림차순 우선순위 큐에 넣고 곱해 주면 되겠다.
</br>

1049: 기타줄

https://www.acmicpc.net/problem/1049

기타줄 싸게 사기

    int min6 = 1001, min1 = 1001;
    for(int i = 0; i < m; i++){
        int m6, m1;
        cin >> m6 >> m1;
        min6 = min(min6, m6);
        min1 = min(min1, m1);
    }
    if( min6 > min1*6 ) cout << n*min1 << endl;
    else{
        if( min6 < (n%6)*min1 ) cout << (n/6 + 1) * min6 << endl;
        else cout << (n/6) * min6 + (n%6)*min1 << endl;
    }

무슨 브랜드가 여러 개 나오고 하는데 그런 거 상관없고 6줄 세트와 1줄 각각 제일 싼 가격만 저장해 둔다.

만~에 하나 6줄 세트보다 낱개로 6줄 사는 게 더 쌀까 봐? 중간에 if문 한 번 넣어서 체크하고,
세트로 살 수 있을 때까지 사고, 남은 줄들이 세트로 사서 줄은 좀 남아도 싸게 치는 지 아니면 낱개로 딱 맞춰 사는 게 싸게 치는 지를 확인하면 된다.
</br>


아직은 막 풀어도 바로 풀리긴 한다…
</br>

댓글남기기