본문 바로가기

백준/세그먼트 트리

[ICPC] 백준 9463 - 순열 그래프

728x90

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

 

각 편에서 번호가 같은 정점끼리 연결했을 때 생기는 교차점으로 순열 그래프를 구성한다고 한다.

 

우리는 교차점의 개수를 구해야 되므로 문제에서 첫번째 그림을 보고 3770번 문제와 같은 흐름으로 inversion counting을 생각할 수 있다.

 

다만 이 문제는 주어진 입력에서 번호가 같은 정점끼리 연결하는 것이므로 이를 적절히 변환해줄 필요가 있다.

 

주어지는 첫번째 노드 집합을 index에 매칭하여 각 숫자가 어느 index에 대응하는지 배열로 저장한다.(mp[val] = idx)

 

두번째 노드집합에서는 index와 첫번재 mp배열에서 해당 노드 숫자의 index를 가져와 pair로 짝지어서 배열이나 선형 자료구조에 저장한다.

 

그렇게 되면 3770번과 같은 형태로 pair 배열을 구성할 수 있고 inversion counting을 해서 답을 구할 수 있다.

 

전체 코드

더보기
#include <bits/stdc++.h>

using namespace std;
using ll = long long;
using pii = pair<int, int>;

int t;

ll fenwick[100001];
int mp[100001];

void add(int idx, int val)
{
    while (idx <= 1e5)
    {
        fenwick[idx] += val;
        idx += (idx & -idx);
    }
}

ll sum(int idx)
{
    ll ret = 0;

    while (idx > 0)
    {
        ret += fenwick[idx];
        idx &= (idx - 1);
    }

    return ret;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> t;
    while (t--)
    {
        ll res = 0;
        memset(fenwick, 0, sizeof fenwick);
        int n;
        cin >> n;

        int idx = 1;

        for (int i = 0; i < n; ++i)
        {
            int x;
            cin >> x;
            mp[x] = idx++;
        }

        vector<pii> v;

        for (int j = 1; j <= n; ++j)
        {
            int x;
            cin >> x;
            v.push_back({j, mp[x]});
        }

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

        for (int k = n - 1; k >= 0; --k)
        {
            res += sum(v[k].second - 1);
            add(v[k].second, 1);
        }

        cout << res << '\n';
    }
}

728x90

'백준 > 세그먼트 트리' 카테고리의 다른 글

백준 13544 - 수열과 쿼리 3  (0) 2021.07.13
[ICPC] 백준 7469 - K번째 수  (0) 2021.07.10
[ICPC] 백준 3770 - 대한민국  (0) 2021.07.09
백준 9426 - 중앙값 측정  (0) 2021.07.08
백준 1777 - 순열 복원  (0) 2021.07.07