GaGe

22863 c++ 본문

알고리즘/[2022] 백준

22863 c++

Sorrel 2022. 12. 11. 14:57

원래 티스토리를 잘 사용하지 않고 있었으나

이 알고리즘에서 틀린 부분이 어디있는지 몰라 고생 중이기에 기록으로 남기고자 포스팅한다.

 

<순열사이클분할 - 수정 전>

#include<iostream>
#include<vector>
using namespace std;
int N, K;
vector<int> S(1000001);
vector<int> D(1000001);
vector<vector<int> >cycles;
vector<bool> check(1000001);
int cnt = -1;
void dfs(int i){
    check[i] = true;
    cycles[cnt].push_back(i);
    if(!check[D[i]]) dfs(D[i]);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin>>N>>K;
    for(int i =1; i<=N; ++i){
        cin>>S[i];
    }
    for(int i =1; i<=N; ++i){
        cin>>D[i];
    }
    for(int i = 1; i<=N; ++i){
        if(!check[i]){
            cycles.push_back(vector<int>());
            cnt++;
            dfs(i);
        }
    }
    vector<long long> result(1000001);
    for(auto cycle : cycles){
        for(int i = 0; i<cycle.size(); ++i){
            result[cycle[(i+K)%cycle.size()]] = S[cycle[i]];
        }
    }
    for(int i =1; i<=N; ++i){
        cout<<result[i]<<' ';
    }
}

<sparse table - 수정 전>

#include <iostream>
#include <vector>
#include <cmath>

using namespace std;
int N;
long long K;
vector<int> S(1000001);
int spt[50][1000001];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> N >> K;
    for (int i = 1; i <= N; ++i) cin >> S[i];
    for (int i = 1; i <= N; ++i) cin >> spt[0][i];
    for (int i = 1; i <= 49; ++i){
        for (int j = 1; j <= N; ++j){
            spt[i][j] = spt[i - 1][spt[i - 1][j]];
        }
    }
    vector<int> result(N + 1);
    for (int i = 1; i <= N; ++i){
        int start = i;
        long long cycle = K;
        for (int j = 50; j >= 0; --j){
            if ((1<<j) <= cycle){
                start = spt[j][start];
                cycle -= (1<<j);
            }
        }
        result[start] = S[i];
    }
    for (int i = 1; i <= N; ++i){
        cout << result[i] << ' ';
    }
}

 

<순열사이클분할>

틀린 점 : K의 타입 지정 실수 int -> long long

 

 

<sparse table>

틀린 점 : 시간 초과

고친 부분 : sparse table을 다 채우기 보다는 K에 맞는 범위까지만 채웠다.

log2(K)까지만 채움

 

틀린 점 : 시프트연산의 범위

고친 부분 : 시프트 연산을 할 때 보통 (1<<n)이런 형식으로 사용하는데 여기서 1은 암묵적으로 int 타입(32비트)이므로 시프트 연산 역시 32번 하게 되면 0으로 없어져버린다. 그러므로 32번 이상 시프트 연산을 할 경우에는 1을 long long 타입으로 미리 지정해줘야 한다.

long long one = 1;

(one<<n); 이런 방법으로 고쳤더니 해결되었다.

 

 

<순열사이클분할 - 수정 후>

#include<iostream>
#include<vector>
using namespace std;
int N;
long long K;
vector<int> S(1000001);
vector<int> D(1000001);
vector<vector<int> >cycles;
vector<bool> check(1000001);
int cnt = -1;
void dfs(int i){
    check[i] = true;
    cycles[cnt].push_back(i);
    if(!check[D[i]]) dfs(D[i]);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin>>N>>K;
    for(int i =1; i<=N; ++i){
        cin>>S[i];
    }
    for(int i =1; i<=N; ++i){
        cin>>D[i];
    }
    for(int i = 1; i<=N; ++i){
        if(!check[i]){
            cycles.push_back(vector<int>());
            cnt++;
            dfs(i);
        }
    }
    vector<int> result(1000001);
    for(auto cycle : cycles){
        for(int i = 0; i<cycle.size(); ++i){
            result[cycle[(i+K)%cycle.size()]] = S[cycle[i]];
        }
    }
    for(int i =1; i<=N; ++i){
        cout<<result[i]<<' ';
    }
}

 

<sparse table - 수정 후>

#include <iostream>
#include <vector>
#include <cmath>

using namespace std;
int N;
long long K;
vector<int> S(1000001);
int spt[50][1000001];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> N >> K;
    for (int i = 1; i <= N; ++i) cin >> S[i];
    for (int i = 1; i <= N; ++i) cin >> spt[0][i];
    for (int i = 1; i <= log2(K); ++i){
        for (int j = 1; j <= N; ++j){
            spt[i][j] = spt[i - 1][spt[i - 1][j]];
        }
    }
    vector<int> result(N + 1);
    for (int i = 1; i <= N; ++i){
        int start = i;
        long long cycle = K;
        for (int j = 50; j >= 0; --j){
            long long one = 1;
            one = (one<<j);
            if (one <= cycle){
                start = spt[j][start];
                cycle -= one;
            }
        }
        result[start] = S[i];
    }
    for (int i = 1; i <= N; ++i){
        cout << result[i] << ' ';
    }
}

'알고리즘 > [2022] 백준' 카테고리의 다른 글

[11727] 2×n 타일링 2 - C++  (1) 2022.09.22
Comments