티스토리 뷰

알고리즘/백준

백준 7578 공장 C++

4567은 소수 2022. 11. 9. 21:17

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

 

7578번: 공장

어떤 공장에는 2N개의 기계가 2열에 걸쳐 N개씩 배치되어 있다. 이 2개의 열을 각각 A열과 B 열이라고 부른다. A열에 있는 N개의 기계는 각각이 B열에 있는 N개의 기계와 하나씩 짝을 이루어 케이블

www.acmicpc.net

주어진 A, B에 대해 같은 수끼리 이었을 때 교차점이 몇 개인지를 구하는 문제입니다.

 

예전에 풀었던 문제와 비슷하여 동일한 방식으로 풀었습니다.

https://ghqls0210.tistory.com/152

 

백준 / 1517 버블 소트 C++

www.acmicpc.net/problem/1517 1517번: 버블 소트 첫째 줄에 N(1≤N≤500,000)이 주어진다. 다음 줄에는 N개의 정수로 A[1], A[2], …, A[N]이 주어진다. 각각의 A[i]는 0≤|A[i]|≤1,000,000,000의 범위에 들어있다. www.acmi

ghqls0210.tistory.com

 

1517번 문제의 경우, 주어진 수열을 버블 소트할 때 스왑이 몇 번 일어나는 지를 구하는 문제였고, 이것을 inversion counting으로 바꿔 문제를 풀면, 머지 소트 과정에서 생기는 교차점의 개수와 동일합니다.

 

이 방법을 7578번에 적용한다면, B의 입력으로 들어온 것을 머지 소트가 된 값으로 생각을 하면 됩니다.

그렇기에 B의 입력으로 들어온 값을 순차적으로 0,1,2,... 라는 새로운 번호를 부여하고 이를 다시 A에 대입하면 (A에는 겹치는 값 없음) 2,0,1,.... 과 같이 무작위 배열 같은 것을 머지소트를 이용해 오름차순으로 정렬하는 것과 동일합니다. 

 

결국 최종적으로 구하는 교차점의 개수와 머지소트 과정에서 발생하는 교차점의 개수가 동일한 것을 가리키므로 답을 구할 수 있습니다.

 

코드는 다음과 같습니다.

#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>

using namespace std;

int n;
int arr[500001];
int tmp[500001];
long long result = 0;

void init()
{
	cin >> n;

    int chk[1000001];
  
	for (int i = 0; i < n; i++) {
		int num;
		cin >> num;
		arr[i] = num;
        chk[num] = i;
	}

    // B에 입력된 값에 0부터 부여
    for (int i = 0; i < n; i++) {
        int num;
        cin >> num;
        int idx = chk[num];
        arr[idx] = i;
    }
}

void merge(int start, int last)
{
	int mid = (start + last) / 2;
	int i = start;
	int j = mid + 1;
	int k = start;
	int cnt = 0;

	while (i <= mid && j <= last) {
		// 왼쪽 배열의 값이 정렬될 때
		if (arr[i] <= arr[j]) {
			tmp[k++] = arr[i++];
			result += (long long)cnt;
		}
		// 오른쪽 배열의 값이 정렬될 때
		else {
			tmp[k++] = arr[j++];
			cnt++;
		}
	}

	// 남은 부분 중 오른쪽 배열의 값이 정렬될 때
	if (i > mid) {
		int s = j;
		while (s <= last) {
			tmp[k++] = arr[s++];
			cnt++;
		}
	}
	// 남은 부분 중 왼쪽 배열의 값이 정렬될 때
	else {
		int s = i;
		while (s <= mid) {
			tmp[k++] = arr[s++];
			result += (long long)cnt;
		}
	}

	for (int t = start; t <= last; t++)
		arr[t] = tmp[t];
}

void mergesort(int start, int last)
{
	if (start < last) {
		int mid = (start + last) / 2;
		mergesort(start, mid);
		mergesort(mid + 1, last);
		merge(start, last);
	}
}

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

	init();
	mergesort(0, n - 1);
	cout << result;
}

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

백준 3108 로고 C++  (0) 2022.12.05
백준 15718 돌아온 떡파이어 C++  (0) 2022.11.10
백준 2957 이진 탐색 트리 C++  (1) 2022.11.05
백준 1562 계단 수 C++  (0) 2022.10.27
백준 2632 피자판매 C++  (0) 2022.10.10
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/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
글 보관함