-
[BOJ] 수열과 쿼리 3PS/BOJ 2020. 8. 23. 23:36
https://www.acmicpc.net/problem/13544
13544번: 수열과 쿼리 3
길이가 N인 수열 A1, A2, ..., AN이 주어진다. 이때, 다음 쿼리를 수행하는 프로그램을 작성하시오. i j k: Ai, Ai+1, ..., Aj로 이루어진 부분 수열 중에서 k보다 큰 원소의 개수를 출력한다.
www.acmicpc.net
알고리즘: Merge sort tree
시간 복잡도: O(NlogN+Mlog2N)
얼핏 봤을 때는 수열과 쿼리 1과 동일한 문제인 것 같지만
이전 쿼리의 결과 값으로 쿼리를 만들어야 한다.
l = a^last_ans
r = b^last_ans
k = c^last_ans
처럼 (a, b, c)가 입력으로 주어지면 이전 결과 값과 XOR을 하여 (l, r, k) 값을 구해야 한다.
따라서 앞에서 사용했던 offline query 기법을 사용할 수는 없다.
지금까지 segment tree는 각 노드에 하나의 값을 저장했고 이를 이용해 각종 쿼리를 처리하였다.
이 선입견에서 벗어나서, 각 노드에 여러 값을 저장해주면 이번 문제를 쉽게 해결할 수 있다.
이번에는, 각 노드에 하나의 값이 아닌 해당 구간에 속하는 모든 Ai의 값이 정렬시켜 저장해보자
그럼 아래 그림과 같이 segment tree가 만들어질 것이다.
그럼 [l, r] 구간 내 k보다 큰 원소의 개수는, 해당하는 노드에서 upper_bound 함수를 사용하여 구할 수 있다.
예를 들어, [2, 5]에서 2보다 큰 원소의 개수를 구해보려면,
색칠된 노드에서 upper_bound를 사용하여 0 + 1 + 1 = 2 라는 값을 구해낼 수 있다.
이러한 자료구조를 merge sort tree 라고 부른다고 한다. (solved.ac tag명을 보아하니)
더보기This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters// 13544: 수열과 쿼리 3 #include<iostream> #include<algorithm> #include<vector> using namespace std; int N, M, a, u, v, k, tree_size = 1, last_ans; vector<int> tree[1<<18]; void updateST(int idx, int val) { idx += tree_size; tree[idx].push_back(val); while (idx > 1) { idx >>= 1; tree[idx].push_back(val); } } int num_overK(int l, int r) { int ans = 0; l += tree_size, r += tree_size; while (l <= r) { if (l & 1) { ans += tree[l].end() - upper_bound(tree[l].begin(), tree[l].end(), k); l++; } if (~r & 1) { ans += tree[r].end() - upper_bound(tree[r].begin(), tree[r].end(), k); r--; } l >>= 1, r >>= 1; } return ans; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> N; while (tree_size < N) tree_size <<= 1; for (int i = 0; i < N; ++i) { cin >> a; updateST(i, a); } cin >> M; for (int i = 1; i <= tree_size; ++i) sort(tree[i].begin(), tree[i].end()); while (M--) { cin >> u >> v >> k; u ^= last_ans; v ^= last_ans; k ^= last_ans; last_ans = num_overK(u-1, v-1); cout << last_ans << "\n"; } return 0; } 'PS > BOJ' 카테고리의 다른 글
[BOJ] 16978 수열과 쿼리 22 (0) 2020.08.24 [BOJ] 16975 수열과 쿼리 21 (0) 2020.08.24 [BOJ] 13537 수열과 쿼리 1 (0) 2020.08.23 [ BOJ] 18436 수열과 쿼리 37 (0) 2020.08.23 [BOJ] 14428,14438 수열과 쿼리 16,17 (0) 2020.08.23