문제링크 : https://www.acmicpc.net/problem/2887


아이디어

  • 모든 행성을 터널로 연결 >> MST
    • Kruscal 사용해서 MST 구하자
  • 간선의 개수 : E = N(N+1)/2 = 1e10/2 = 5e9
    • MST 시간복잡도 : O(ElgE) > 시간초과
    • 간선을 모두 넣는 경우에는 시간초과가 발생
  • 문제 중 비용 = min(x, y, z)을 이용
    • x,y,z 좌표의 차이를 각각 넣고, 이중 최소값만 사용하면됨
      • 크루스칼에서 자연스럽게 최소의 간선만 적용될 것임
    • 모든 노드의 간선을 넣지말고. 정렬한뒤 근접한 것만 적용
      • 어짜피 최소값만 MST에서 살아남게됨
      • 그러므로 정렬 시킨다음에 인접한 것이 가장 작은 값

시간복잡도 계산

  • x,y,z 좌표에 대해서 각각 정렬 : O(3 * NlgN)
    • 인접한 노드에 대해서 간선 추가 : O(3 * N)
    • MST 시간복잡도 : ElgE
      • 간선의 개수(E): 3N
      • 3Nlg3N
    • 총합 : O(3NlgN + 3N + 3Nlg3N) = O(NlgN)

인트 계산

  • 간선 의 길이 최대값 : 2e9 > INT 가능
  • 최소비용 : 2e9 *N-1 >> long long 사용

코드

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream>
#include <tuple>
#include <algorithm>
#include <vector>
#include <cmath>
 
using namespace std;
typedef tuple<intintint> ti3;
typedef pair<intint> pi2;
typedef long long ll;
 
vector<ti3> edge;
int p[100010];
vector<pi2> xnode;
vector<pi2> ynode;
vector<pi2> znode;
 
int N;
 
int find(int v) {
    if(p[v] < 0return v;
    return p[v] = find(p[v]);
}
 
bool is_diff_group(int v1, int v2) {
    v1 = find(v1); v2 = find(v2);
    if(v1 == v2) return 0;
    
    if(p[v1] == p[v2]) p[v1]--;
    
    if(p[v1] < 0) p[v2] = v1;
    else p[v1] = v2;
    return 1;
    
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    fill(p, p+100010-1);
    cin >> N;
    
    // 각 좌표 넣기
    // 이때 노드 인덱스랑 같이 넣어줌 정렬후 확인하기 위해
    for(int i=0; i<N; i++) {
        int ex, ey, ez;
        cin >> ex >> ey >> ez;
        xnode.push_back(make_pair(ex, i));
        ynode.push_back(make_pair(ey, i));
        znode.push_back(make_pair(ez, i));
    }
    
    // 간선수 줄이기위해 정렬
    sort(xnode.begin(), xnode.end());
    sort(ynode.begin(), ynode.end());
    sort(znode.begin(), znode.end());
    
    // 인접한 노드를 엣지에 추가
    for(int i=0; i<N-1; i++) {
        edge.push_back({abs(xnode[i].first - xnode[i+1].first),xnode[i].second,xnode[i+1].second});
        edge.push_back({abs(ynode[i].first - ynode[i+1].first),ynode[i].second,ynode[i+1].second});
        edge.push_back({abs(znode[i].first - znode[i+1].first),znode[i].second,znode[i+1].second});
    }
    
    // 간선들 정렬
    sort(edge.begin(), edge.end());
    
    int cnt=0;
    ll ans=0;
    // Kruscal 수행
    for(int i=0; i<edge.size(); i++) {
        int cost, a,b; tie(cost,a,b) = edge[i];
        if(!is_diff_group(a,b)) continue;
        
        cnt++;
        ans += cost;
        if(cnt==N-1break;
    }
    
    cout << ans << '\n';
    
    
    return 0;
}
 
cs

문제유형

  • MST - 간선의 특수 조건
    • 간선의 비용이 특수한 경우
    • 일반적으로 하면 간선의 개수가 많아서 시간초과 발생
    • 간선의 조건 활용해 그리디하게 사용 가능

문제링크 : https://www.acmicpc.net/problem/10942


아이디어

  • 팰린드롬 개념

    • 팰린드롬 : 앞에서 읽으나 뒤에서 읽으나 같은 단어
    • 문자열에서 접두사와 접미사가 겹치는 부분이 발생(이때 홀수로 겹쳐서 대칭되어야함)
    • 구하는 방법 :
      • KMP
        • 접두사와 접미사가 같은 길이(f[s.size()-1])에서 반복하는 문자열(s.size()-f[s.size()-1])으로 나누어 떨어지지 않을때
        • f[s.size()-1] % (s,size() - f[s.size()-1])
      • DP
        • DP[st][en] : st부터 시작해서 en까지 끝날때 팰린드롬 true, false
        • DP[st][en] = true일때, 각각 앞뒤 문자열이 같을경우(arr[st-1] == arr[en+1]) dp[st-1][en+1] = true
    • KMP 사용할 경우
      • 1부터 계산하는건 문제가 안됨
      • 중간부터 계산하는 건 어떻게 진행?
      • 매번 KMP를 다시구할경우
        • O(M * N) = 2e9 > 시간초과
      • KMP 사용해서는 불가
    • DP 사용할 경우
      • 숫자들에 대해 미리 DP를 구해놓고
      • 각각의 요청에 따라 DP 값 출력

시간복잡도 계산

  • DP 구하기 : O(N^2)
  • 요청에라 확인 : O(M)
  • 합 : O(N^2+M) : 4e6 + 1e6

인트 계산

  • 입력 숫자값 최대 1e5
    • DP 값 : true, false

코드

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
#include <iostream>
 
using namespace std;
 
int arr[2010];
int dp[2010][2010];
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    int N; cin >> N;
    for(int i=0; i<N; i++cin >>arr[i];
    
    fill(&dp[0][0], &dp[2009][2010], 0);
    
    // 길이 1일때
    for(int i=0; i<N; i++) dp[i][i] = 1;
    
    // 길이 2일때
    for(int i=0; i<N-1; i++if(arr[i] == arr[i+1]) dp[i][i+1= 1;
    
    // 길이 3이상
    // 각 길이 케이스에서
    for(int l=2; l<N; l++) {
        // 시작하는 곳
        for(int i=0; i<N-l; i++) {
            if(arr[i] == arr[i+l] && dp[i+1][i+l-1]) dp[i][i+l] = 1;
        }
    }
    
    int M; cin >> M;
    for(int i=0; i<M; i++) {
        int j,k; cin >> j >> k;
        cout << dp[j-1][k-1<< '\n';
    }
    
    return 0;
}
 
cs

문제유형

  • DP - 팰린드롬
    • 팰린드롬 : 앞에서 읽으나 뒤에서 읽으나 같은 단어
    • DP[st][en] : st부터 시작해서 en까지 끝날때 팰린드롬 true, false
    • DP[st][en] = true일때, 각각 앞뒤 문자열이 같을경우 팰린드롬
    • 문자길이 1,2, 3이상일때 각각 나눠서 수행

문제링크 : https://www.acmicpc.net/problem/4354


문제 추상화

  • 각 문자가 몇번 반복되는지 찾아야함
  • 근데 연속해서 반복되어야함, 겹치거나 띄어서 반복되면안됨(일반 KMP와 다름)

아이디어

  • 문자열의 앞에서부터 자른다음 연속하는지 확인

    • 앞에서부터 자르는건 약수인지 확인
    • 다음 문자부터 문자열길이 단위만큼 비교
    • 시간복잡도 계산
      • 문자열 자르기 , 약수개수: O(M)
      • 문자열 길이 단위만큼 비교 : O(M)
      • O(M*M) : 1e12 시간초과
    • KMP 사용
      • KMP의 fail 배열 : 해당 인덱스에서 접두사와 접미사가 같은것의 개수
      • 각 문자열의 fail 배열을 구할경우, 마지막 값을 통해 몇번 반복되는지 확인할 수 있음
        • fail배열의 마지막값 : 해당 문자열의 접두사와 접미사가 같은 최대의 길이
        • 전체 문자열의 길이에서 이 최대의 길이뺀 값이 전체 문자열에서 반복하는 문자열
      • 단, 접두사와 접미사가 중간에 겹치는경우(팰린드롬 제외)

시간복잡도 계산

  • 모든 문자열에 대해서 O(10)
  • fail 함수 구함 : O(M)
  • 합 : O(M) = 1e6

인트 계산

  • 접두사와 접미사가 같은 최대 길이 : 1e6

코드

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
#include <iostream>
#include <string>
#include <vector>
 
 
using namespace std;
 
 
vector<int> fail(string& s) {
    vector<int> f(s.size());
    
    int j=0;
    for(int i=1; i<s.size(); i++) {
        while(j>0 && s[i] != s[j]) j = f[j-1];
        if(s[i] == s[j]) f[i] = ++j;
    }
    
    return f;
    
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    
    while(1) {
        string s; cin >> s;
        if(s == "."break;
        
        int maxv = 0;
        vector<int> f = fail(s);
        
        
        if(f[s.size()-1] % (s.size() - f[s.size()-1])) cout << 1 << '\n';
        else cout <<s.size()/(s.size()-f[s.size()-1]) << '\n';
    }
    return 0;
}
 
cs

문제유형

  • KMP - 문자열 제곱
    • 문자열 안에서 작은 문자열이 최대 몇개 반복되는지 확인
    • 문자열 길이 - fail 함수의 마지막 인덱스 = 반복되는 문자 길이
    • 단, 접두사와 접미사가 중간에 겹치는 경우 확인(팰린드롬)

문제링크 : https://www.acmicpc.net/problem/14725


아이디어

  • 계층구조 trie로 표현한다음
  • 규칙에 맞도록 출력(DFS)
    • 출력할떄 알파벳순서로 어떻게 정렬하지?
    • child가 map 순서대로를 이용

시간복잡도 계산

  • trie생성
    • 모든 입력에 대해 : O(N)
    • 모든 먹이개수에 대해 trie 생성: O(K)
    • 총합 : O(NK)
  • trie 출력, DFS
    • DFS 출력 : O(V+E)
    • V : 노드개수 : NK
    • E : 노드간선개수 : NK
    • O(NK)
  • 합 : O(NK) : 1.5e4

인트 계산

  • 노드 인덱스 : 최대 NK

코드

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
59
60
61
62
63
#include <iostream>
#include <vector>
#include <map>
#include <string>
 
using namespace std;
 
struct node {
    bool fin;
    map<stringint> child;
    string cur;
    node(string s) {
        fin = false;
        cur = s;
        child.clear();
    }
};
 
vector<node> trie;
 
int insert(int nodi, string s) {
    
    if(trie[nodi].child[s] == 0) {
        trie[nodi].child[s] = trie.size();
        trie.push_back(s);
    }
    
    return trie[nodi].child[s];
}
 
void dfs(int cur, int depth) {
    if(cur != 0) {
        for(int i=0; i<depth-1; i++cout << "--";
        cout << trie[cur].cur <<'\n';
    }
    for(auto it = trie[cur].child.begin(); it!=trie[cur].child.end(); it++) {
        dfs(it->second, depth+1);
    }
}
 
 
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    int N; cin >> N;
    
    trie.push_back(node(""));
    
    while(N--) {
        int en; cin >> en;
        int pre = 0;
        while(en--) {
            string es; cin >> es;
            pre = insert(pre, es);
        }
    }
    
    dfs(0,0);
    
    return 0;
}
 
cs

문제유형

  • TRIE - 여러글자
    • 일반 TRIE가 한글자씩 정보 저장
    • 여러글자를 가지고 TRIE
    • node의 child에 알파벳이나 숫자갯수만큼 저장하는 것이 아닌
    • map을 가지고 다음 노드를 관리

문제링크 : https://www.acmicpc.net/problem/4358


아이디어

  • 자료구조 map 사용
  • 각 나무를 맵에 넣은다음에 추가될때마다 카운트 증가
    • 나무의 키들을 뽑아 정렬
    • 전체 개수중에 각 나무의 카운트를 출력

시간복잡도 계산

  • 맵에 넣기 O(M)
  • 맵 키 정렬O(NlgN)
  • 각 나무의 카운트를 출력

인트 계산

  • 최대 나무개수 e6 가능

코드

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
#include <iostream>
#include <string>
#include <map>
#include <cmath>
 
using namespace std;
 
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    map<stringint> tree;
    int cnt=0;
    
    string s;
    while(getline(cin, s)) {
        cnt++;
        tree[s]++;
        
    }
    cout <<fixed;
    cout.precision(4);
    
    for(auto it = tree.begin(); it !=tree.end(); it++) {
        cout << it->first << ' ' << round(it->second/(double)cnt*1000000)/10000 << '\n';
    }
    return 0;
}
 
 
 
cs

문제유형

  • 자료구조 - map

문제링크 : https://www.acmicpc.net/problem/3665


문제 추상화

  • 기존의 순서가 주어지고
  • 바뀌어야할 순서 주어질떄
  • 새로운 순서 구하기

아이디어

  • topological sort 사용

  • 바뀐 순서 따라가면서 adj에 추가

  • 그럼 기존에 만들었던 adj는 어떻게하지?

    • 인접한건 뺼수 있는데
    • 인접하지 않은건?
  • adj추가할때 후순위를 모두 넣으면 가능?

    • 그럼 인접하지 않은것도 확인가능
  • 순위를 찾을수 없는 경우 : 큐에 한번에 두개 이상이 들어올떄

  • 데이터 일관성 없어서 순위 못정하는 경우 : 전체 사이즈가 N이 안될때


시간복잡도 계산

  • 테스트케이스 O(T)
  • 각 노드에서 adj, indeg 생성(O(N^2))
  • 바뀐쌍마다 adj수정 : O(M * N)
  • topo 수행 : O(V+E) : O(N^2)
  • 총합 : O(T * (N^2 + MN + N^2)) = O(T*MN) = 1e9 (약간 불안)

인트 계산

  • indeg밖에없는데, 최대 N 가능

코드

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
 
using namespace std;
 
bool chk[510];
vector<int> adj[510];
int indeg[510];
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    int t; cin >> t;
    while(t--) {
        fill(chk, chk+5100);
        fill(indeg, indeg+5100);
        for(int i=0; i<510; i++) adj[i].clear();
        
        int N; cin >> N;
        for(int i=0; i<N; i++) {
            int e; cin >> e;
            chk[e]=1;
            for(int j=1; j<=N; j++) {
                if(chk[j] == false) {
                    adj[e].push_back(j);
                    indeg[j]++;
                }
            }
        }
        
        int M; cin >> M;
        for(int i=0; i<M; i++) {
            int a,b; cin >> a >> b;
            vector<int>::iterator it = find(adj[b].begin(), adj[b].end(), a);
            if(it != adj[b].end()) {
                adj[b].erase(it);
                indeg[a]--;
                adj[a].push_back(b);
                indeg[b]++;
            } else {
                it = find(adj[a].begin(), adj[a].end(), b);
                adj[a].erase(it);
                indeg[b]--;
                adj[b].push_back(a);
                indeg[a]++;
            }
        }
        
        vector<int> rs;
        queue<int> q;
        for(int i=1; i<=N; i++) {
            if(indeg[i] == 0) q.push(i);
        }
        
        // 확실한 순위를 찾을수 없을때가 언제지?
        // 서로 순서가 꼬이면
        // 예를들면 1,2,3 인데 1,3만 바뀌면 2,3 관계가 순서가 꼬임
        // 순서가 꼬이는경우 > 큐에 여러개 들어갈때
        bool sw = false;
        while(!q.empty()) {
            if(q.size() >1) {
                sw= true;
                break;
            }
            int eq = q.front(); q.pop();
            rs.push_back(eq);
            
            for(int x : adj[eq]) {
                indeg[x]--;
                if(indeg[x] == 0) q.push(x);
            }
            
        }
        if(sw == truecout << '?' << '\n';
        else if(rs.size() != N) cout << "IMPOSSIBLE" << '\n';
        else {
            for(int x : rs) cout << x << ' ';
            cout << '\n';
        }
        
    }
    return 0;
}
 
cs

문제유형

  • 순위를 찾을 수 없는 경우
    • 큐에 한번에 여러개의 노드가 들어갈때
  • 일관성 없는 경우
    • 사이클이 발생한 것
    • 결과의 사이즈가 노드 개수랑 다를때

문제링크 : https://www.acmicpc.net/problem/1654


아이디어

  • 랜선의 길이를 정한다음, K개의 랜선에 각각 나눠보면서 N개 이상이 되는 최대의 개수를 구하면됨
    • 정답이 되는 랜선의 길이를 가지고 이진 탐색 수행
      • 구하려는 랜선길이 이분탐색
      • 이분탐색할때 K개에 대해서 나눠줌
      • N개 이상이 되는 최대 길이를 구함 > upper bound

시간복잡도 계산

  • 구하려는 랜선길이 이분탐색 : lg(2^31)
    • 이분탐색할때 K개에 대해서 나눠줌 : O(K)
    • O(lg(2^31) * K) = 31 * 1e4 = 3e5

인트 계산

  • 이미 가지고 있는 랜선길이 : 1~2^31 = int 가능
  • 자를수 있는 갯수 계산할때 :
    • 제일 작은 1로 자른다고 쳤을때
    • 최대값 : 2^31 * K >> long long 사용

코드

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
#include <iostream>
#include <algorithm>
#include <cmath>
 
using namespace std;
typedef long long ll;
 
int K,N;
int nums[10010];
 
//
ll cal(int mid) {
    ll rs=0;
    for(int i=0; i<K; i++) rs+=nums[i]/mid;
    
    return rs;
}
int binsearch(ll st, int en, int tar) {
    if(st==en) {
        return st;
    }
    
    int mid = (st+en+1)/2;
    if(cal(mid) >= tar) {
        return binsearch(mid, en, tar);
    }
    else return binsearch(st, mid-1, tar);
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    cin >> K >> N;
    for(int i=0; i<K; i++cin >> nums[i];
    
    cout << binsearch(1,pow(2,31)-1, N) << '\n';
}
 
cs

문제유형

  • 이분탐새 - 케이스를 이분탐색

비슷한 문제

문제링크 : https://www.acmicpc.net/problem/10815



아이디어

  • 포함하고있는지 확인 >> 이분탐색

시간복잡도 계산

  • N개에 대해 정렬 : O(NlgN)
  • M개에 대해 이분 탐색 : O(M * lgK )
  • 합 : O(NlgN + MlgK)

인트 계산

  • 각 숫자의 최소 -1e7, 최대 1e7 > INT 가능

코드

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
#include <iostream>
#include <algorithm>
 
using namespace std;
 
int nums[500010];
 
 
void binsearch(int st, int en, int tar) {
    if(st==en) {
        if(nums[st] == tar) cout << 1 << ' ';
        else cout << 0 << ' ';
        return;
    }
    
    int mid = (st+en)/2;
    
    if(nums[mid] < tar) binsearch(mid+1, en, tar);
    else binsearch(st, mid, tar);
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int N; cin >> N;
    for(int i=0; i<N; i++cin >> nums[i];
    
    sort(nums, nums+N);
    
    int M; cin >> M;
    for(int i=0; i<M; i++){
        int a; cin >> a;
        binsearch(0,N-1,a);
    }
}
 
cs

문제유형

  • 이분탐색 기본

문제링크 : https://www.acmicpc.net/problem/1965


문제 추상화


아이디어

  • N의 크기가 작으니까 DP로 해결
    • DP[X] = X 위치에서 한번에 넣을수 있는 상자 개수의 최대값
      • 점화식
    • DP[X] = max(if(arr[x] > arr[i]) DP[i]+1)
    • 순회 돌면서, 상자의 값이 더 클경우, DP값+1의 최대값

시간복잡도 계산

  • 각 노드에서 이전 노드 모두 돌아야함 : O(N^2) > 1e6

인트 계산

  • DP값 : 최대 1000 > INT 가능

코드

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
#include <iostream>
 
using namespace std;
 
int dp[1010];
int map[1010];
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    
    int maxv = 1;
    
    int N; cin >> N;
    fill(dp, dp+N, 1);
    for(int i=0; i<N; i++cin >> map[i];
    
    for(int j=0; j<N; j++) {
        for(int i=0; i<j; i++) {
            
            if(map[j] > map[i]) {
                dp[j] = max(dp[j], dp[i]+1);
                maxv = max(maxv, dp[j]);
            }
        }
    }
    
    cout << maxv << '\n';
    return 0;
}
 
cs

문제유형

  • DP - LIS
    • DP에서 순차적으로 오는것이 아닌, 여러 경로가 있을떄 사용
    • 특히 2차원에서 상하좌우를 모두 고려해줘야할 때

비슷한 문제

문제링크 : https://www.acmicpc.net/problem/1715

 

아이디어

  • 두묶음씩 합칠때, 카드 개수가 많은 묶음일수록 합쳐지는 횟수가 적어야함
  • 정렬한다음, 두개씩 묶어나감
    • 이렇게하면 문제 발생
    • A,B,C,D 에서, A,B 더한값이 C,D보다 작을경우엔
    • (A + B) + (C+D) 보다, ((A+B)+C)+D 가 맞음
  • 그럼 정렬해서 앞의 두개씩만 더하자
    • pq 사용

 

시간복잡도 계산

  • 처음 정렬 : O(NlgN)
  • 앞의 두개씩 계산 : O(N * lgN)
  • 합 : O(NlgN)

 

인트 계산

  • 최대 카드 합의 값 : 1e3* 1e5 * lg(1e5) = 1e8 + 20 > 2e9, 안전하게 ll 사용

 

코드

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
#include <iostream>
#include <algorithm>
#include <queue>
 
using namespace std;
typedef long long ll;
 
 
int main() {
    int N; cin >> N;
    priority_queue<ll,vector<ll>, greater<ll>> pq;
 
    for(int i=0; i<N; i++) {
        ll a; cin >> a;
        pq.push(a);
    }
    
    
    ll rs=0;
    
    while(pq.size() != 1) {
        ll a = pq.top(); pq.pop();
        ll b = pq.top(); pq.pop();
        pq.push(a+b);
        rs+=(a+b);
    }
    
    
    cout << rs << '\n';
    
    return 0;
}
 
cs

 

문제유형

  • 그리디 - 두개씩 합치기
    • 더할수록 이전 비용까지 합해서 발생하는 경우
    • 큰 수는 가장 마지막에 계산
    • 우선순위 큐를 사용하여 가장 앞에 두개씩 더해서 추가

 

 

+ Recent posts