알고리즘/백준

[백준/BOJ/7578] 공장

코딩하는 회사원 2024. 3. 23. 18:48
728x90

세그먼트 트리 or 펜윅 트리를 사용해야 하는 문제다.

 

원리는 이와 같다.

입력
5
132 392 311 251 231
392 351 132 311 231

 

A 배열의 index 를 처음부터 찾아 나가면서, 그 뒤에 있는 구간 합을 result 에 더해주는 방식이다.

index 1 2 3 4 5 Result
A 132 392 311 351 231 0
B (Tree 의 IDX) 392 351 132 311 231 0
Tree [A[1]]
--> Tree[3]
0 0 1 0 0 0+
Tree[4-5]
Tree [A[2]]
--> Tree[1]
1 0 1 0 0 1 +
Tree[2-5]
Tree[A[3]]
--> Tree[4]
1 0 1 1 0 1 +
Tree[5]
Tree[A[4]
--> Tree[2]
1 1 1 1 0 3
+ Tree[3-5]
Tree[A[5]]
--> Tree[5]
1 1 1 1 1 3 + nothing

 

1) 펜윅 코드

#include <iostream>
#include <map>
using namespace std;
const int MAX = 5e5 + 1;
int N, tree[MAX], arr[MAX];
map<int, int> mp;
void update(int i,int val) {
	while (i <= N) {
		tree[i] += val;
		i += (i & -i);
	}
}
int sum(int i) {
	int ret = 0;
	while (i > 0) {
		ret += tree[i];
		i -= (i&-i);
	}
	return ret;
}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	cin >> N;
	for (int i = 1; i <= N; i++) cin >> arr[i];
	for (int i = 1; i <= N; i++) {
		int num; cin >> num;
		mp[num] = i;
	}
	long long res = 0;
	for (int i = 1; i <= N; i++) {
		int lsum = sum(mp[arr[i]]);
		int rsum = sum(N);
		res += (rsum - lsum);
		update(mp[arr[i]], 1);
	}
	cout << res << "\n";
	return 0;
}

 

2) 세그 코드

#include <iostream>
#include <map>
using namespace std;
const int MAX = 5e5 + 1;
int N, arr[MAX], tree[MAX * 3];
map<int, int> mp;
int query(int node, int start, int end, int left,int right) {
	if (right<start || left>end) return 0;
	if (left <= start && end <= right) return tree[node];
	int lsum = query(node * 2, start, (start + end) / 2, left, right);
	int rsum = query(node * 2 + 1, (start + end) / 2 + 1, end, left, right);
	return lsum + rsum;
}
void update(int node, int start, int end, int index, int value) {
	if (index<start || index>end) return;
	if (start == end) {
		tree[node] = value;
		return;
	}
	update(node * 2, start, (start + end) / 2, index, value);
	update(node * 2 + 1, (start + end) / 2 + 1, end, index, value);
	tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	cin >> N;
	for (int i = 1; i <= N; i++) cin >> arr[i];
	for (int i = 1; i <= N; i++) {
		int num; cin >> num;
		mp[num] = i;
	}
	long long res = 0;
	for (int i = 1; i <= N; i++) {		
		res += query(1, 1, MAX, mp[arr[i]] + 1, MAX);
		update(1, 1, MAX, mp[arr[i]], 1);
	}
	cout << res << "\n";
	return 0;
}

 

3) 성능 차이 (펜윅이 아래)

728x90