티스토리 뷰

Computer Science/BOJ

BOJ 1202. LOPOV

yeongminb 2024. 8. 6. 17:13
반응형

문제 링크

 

문제 풀이

 이 문제는 $N\leq 3\times 10^5$개의 보석과 $K\leq 3\times 10^5$개의 가방이 주어지고, 각 보석의 무게 $M_{i}$, 가격 $V_{i}$와 가방에 담을 수 있는 최대 무게 $C_{i}$가 주어질 때 담을 수 있는 보석의 최대 가격을 출력하는 문제이다. 

 

 일단 당연히 최대 가격을 얻기 위해선 보석들 중 가격이 높은 순서대로 가방에 넣는 것을 시도해야 한다. 그래서 그리디 알고리즘으로 생각해보면 가격이 높은 보석들부터 가방에 넣는데, 그 가방의 무게는 보석의 무게를 넘는 최소의 무게(lower bound)일 수록 좋을 것이다. 만약 만족하는 가방이 없거나 이미 보석을 넣은 상태라면 넣지 못할 것이다. 이렇게 생각하면 일단 보석에 대해 iteration을 할 때, $O(N)$이고 여기서 가방을 찾는데 $O(logK +K)$이므로 $O(N(K+logK))$의 자명한 풀이를 얻을 수 있다. 이건 당연히 시간초과가 난다.

 

 그래서 가방을 찾는데 $O(logK)$만 걸리도록 수정을 할 생각을 했다. $O(K)$가 추가로 걸리는 이유는 lowerbound로 찾은 가방에, 이전에 보석이 넣어져서 다음 가방을 탐색해야하는 경우가 발생하면 최악에 경우 $K-1$번 다른 가방을 확인해야하기 때문이다. 그래서 각 가방에, 다음 가방으로 가능한 가방에 대한 정보를 추가적으로 저장해주면 $O(1)$만에 확인할 수 있을 것이다.

 

pair<long long, int> Bag[KMAX];

 

 그래서 가방을 저장하는 배열을 pair로 만들었는데 앞에 long long부분이 가방의 최대 무게이고, 뒤에 int부분이 다음 가방의 번지수이다. 보석이 들어있는 않는 경우는 int부분이 자신의 번지수로 설정되어있을 것이다.

 추가적으로 $O(1)$으로 근사시키기 위해 경로 압축을 이용할 수 있다. 

 

 전체적으로 시간복잡도를 구해보면 $O(NlogK)$로 근사된다.

 

 

 

 

시행착오

$\cdot$ long long으로 안해놔서 오버플로우가 발생한 거 같다.

$\cdot$ 경로 압축을 안해줘서 TLE를 받았다.

 

 

 

 

코드

#include <iostream>
#include <algorithm>
using namespace std;
#define KMAX 300000
#define NMAX 300000
typedef long long ll;

ll N,K,MXPRICE=0;
pair<ll,ll> Jewel[NMAX];
pair<ll, int> Bag[KMAX];
ll Bag1[KMAX];

void input(){
    cin>>N>>K;
    for(int i=0;i<N;i++){
        ll m,v;
        cin>>m>>v;
        Jewel[i] = {v,m};
    }
    for(int i=0;i<K;i++){
        ll C;
        cin>>C;
        Bag[i] = {C,0};
    }
}

void init(){
    sort(Bag,Bag+K);
    sort(Jewel,Jewel+N,greater<pair<ll,ll>>());
    for(int i=0;i<K;i++){
        Bag[i].second = i;
        Bag1[i] = Bag[i].first;
    }
}

int find(int x){
    if(x==-1||x==Bag[x].second) return x;
    return Bag[x].second = find(Bag[x].second);
}
void solve(){
    for(int i=0;i<N;i++){
        ll V = Jewel[i].first;
        ll M = Jewel[i].second;
        int lb = lower_bound(Bag1,Bag1+K,M) - Bag1;
        if(Bag[lb].first<M) continue;
        int k = find(lb);
        if(Bag[k].first<M||k == -1) continue;
        MXPRICE += V;
        if(k==K-1) Bag[k].second = -1;
        else Bag[k].second = Bag[k+1].second;
    }
}

void output(){
    cout<<MXPRICE;
}

int main(){
    cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
    input();
    init();
    solve();
    output();
}

'Computer Science > BOJ' 카테고리의 다른 글

BOJ 15486. 퇴사 2  (2) 2024.08.27
BOJ 2887. 행성터널  (2) 2024.08.17
BOJ 32069. 가로등  (1) 2024.07.24
BOJ 14500. 테트로미노  (1) 2024.06.08
BOJ 16891. 탄성충돌  (0) 2024.03.24
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/12   »
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
글 보관함