알고리즘/BOJ 문제풀이

[백준] 16225 제271회 웰노운컵

4Legs 2021. 2. 16. 16:11

문제 링크 : www.acmicpc.net/problem/16225

 

16225번: 제271회 웰노운컵

첫 줄에 짝수 N(2 ≤ N ≤ 200,000)이 주어진다. 다음 줄에 A[1], ..., A[N], 그 다음 줄에 B[1], ..., B[N]이 (1 ≤ A[i], B[i] ≤ 109) 주어진다. 모든 A[i]는 서로 다르고, 모든 B[i]도 서로 다르다.

www.acmicpc.net

문제 유형

Greedy

 

문제 두 개를 선택했을 때, 항상 상대는 B값이 더 큰 문제를 가져간다 했으므로, 주어진 문제들을 B값의 오름차순으로 정렬해 보자.

정렬 후 알 수 있는 사실은 다음과 같다.

즉, 2k + 1 번까지의 문제 중에서 k + 1 개의 문제를 가져갈 수 있고, 이 때 문제를 어떤 조합으로 고르던 항상 배분을 완료할 수 있으므로,

A[i]값이 가장 높은 k + 1개의 문제를 고르면 문제의 정답을 구할 수 있다.

따라서, 2번 문제부터 고를 수 있는 문제의 범위를 2씩 늘려 가며 그때마다 가장 높은 A[i]값을 갖는 문제를 골라 그 A[i]값을 정답에 더해주면 된다.

 

예를 들어, 위의 예시에서 k = 1일 때 고를 수 있는 문제의 범위는 2 ~ 3이다. 따라서, 3번 문제를 고른다.

다음으로 k = 2일 때, 고를 수 있는 문제의 범위는 2 ~ 5이다. 따라서, 5번 문제를 고른다.

k = 3일 때, 고를 수 있는 문제의 범위는 2 ~ 7이다. 따라서, 7번 문제를 고른다.

마지막으로 k = 4일 때, 고를 수 있는 문제의 범위는 2 ~ 9이다. 따라서, 8번 문제를 고른다.

결과적으로 얻을 수 있는 최대 A[i]값의 합은 (2 + 9 + 8 + 6 + 7) = 32 이다.

 

[코드]

최대 A[i] 값을 구하는 데 우선순위 큐를 사용한다. 아래 코드는 시작 인덱스가 0이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
 
using namespace std;
typedef long long ll;
typedef pair<intint> p;
 
int n, A[200001], B[200001];
vector<p> question;
 
ll greedy() {
    ll ret = question[0].first;        //첫 문제는 반드시 A의 것이 된다.
    priority_queue<int> pque;
    
    for (int i = 1; i < n / 2; i ++) {
        //두 문제를 큐에 삽입
        pque.push(question[2 * i - 1].first);
        pque.push(question[2 * i].first);
 
        //1 ~ 2i + 1(홀수 개) 까지의 문제들 중 가장 A값이 큰 문제를 고른다.
        int top = pque.top();
        ret += top;
        pque.pop();
    }
 
    return ret;
}
 
bool b_asc(p a, p b) {
    return a.second < b.second;
}
 
void init() {
    int a, b;
    cin >> n;
 
    for (int i = 0; i < n; i++cin >> A[i];
    for (int i = 0; i < n; i++cin >> B[i];
    for (int i = 0; i < n; i++) question.push_back({ A[i], B[i] });
 
    //B[i] 오름차순 정렬
    sort(question.begin(), question.end(), b_asc);
}
 
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(NULL);
 
    init();
    ll answer = greedy();
    printf("%lld\n", answer);
 
    return 0;
}
cs

'알고리즘 > BOJ 문제풀이' 카테고리의 다른 글

[백준] 1849 순열  (0) 2021.02.25
[백준] 1289 트리의 가중치  (2) 2021.02.17
[백준] 1135 뉴스 전하기  (0) 2021.02.10
[Sweeping] BOJ 7626 직사각형  (4) 2021.02.04
[Sweeping] BOJ 3392 화성 지도  (0) 2021.02.04