티스토리 뷰
문제
문제 분류
- 난이도 - 중
- 태그 - 구간 트리
문제 풀이
각 점에 대해서 자신의 위치보다 \(x\) 값이 크거나 같으면서, \(y\)값은 작거나 같은 지점들을 모두 세면 되는 문제다. 그런데 \(n\)의 값을 보면 알겠지만, 단순하게 모두 다 해보는 \(O(N^2)\) 방식으로는 안된다. 구간 트리를 사용하면 이 정보를 빠르게 셀 수 있다.
먼저 좌표들을 (1) \(x\)값이 감소하는 방향으로, (2) \(y\) 값이 증가하는 방향으로 정렬한다.
그런 다음에 유일한 \(y\) 좌표들을 가지고 구간 트리를 구성한다. 이제 앞서 점들을 정렬한 순서대로 하나씩 자신보다 \(x\) 값이 크거나 같은 점들 중에서 \(y\) 값이 작거나 같은 좌표들을 구간 합 트리에 질의를 하여 찾아낸다. 그런 다음에 자신의 \(y\) 좌표에 해당하는 트리의 구간(위치)에 +1을 하면 된다.
소스 코드
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | #include <iostream> #include <string> #include <algorithm> #include <cstring> #include <cmath> #include <vector> #include <cstdlib> #include <stack> #include <queue> #include <set> #include <map> using namespace std; struct RangeSum { int n; vector< int > tree; RangeSum( const vector< int >& a) { n = a.size(); if (n == 0) return ; tree.assign(n * 4, 0); } int query( int p, int left, int right, int qLeft, int qRight) { if (qLeft > right || qRight < left) return 0; if (qLeft <= left && right <= qRight) return tree[p]; int mid = (left + right) / 2; return query(p * 2, left, mid, qLeft, qRight) + query(p * 2 + 1, mid + 1, right, qLeft, qRight); } int update( int p, int left, int right, int you, int plus) { if (you < left || you > right) return tree[p]; if (left == right) return tree[p] += plus; int mid = (left + right) / 2; return tree[p] = update(p * 2, left, mid, you, plus) + update(p * 2 + 1, mid + 1, right, you, plus); } int query( int qLeft, int qRight) { return query(1, 0, n - 1, qLeft, qRight); } void update( int you, int plus) { update(1, 0, n - 1, you, plus); } }; bool predicate( const pair< int , int >& lhs, const pair< int , int >& rhs) { if (lhs.first != rhs.first) return lhs.first > rhs.first; return lhs.second < rhs.second; } int main() { int T; scanf ( "%d" , &T); while (T--) { int n; scanf ( "%d" , &n); vector<pair< int , int >> locations; vector< int > a; for ( int i = 0; i < n; i++) { int x, y; scanf ( "%d%d" , &x, &y); locations.emplace_back(x, y); a.push_back(y); } sort(locations.begin(), locations.end(), predicate); sort(a.begin(), a.end()); a.erase(unique(a.begin(), a.end()), a.end()); RangeSum rSum(a); long long ans = 0; for ( int i = 0; i < n; i++) { int qLeft = 0; int qRight = lower_bound(a.begin(), a.end(), locations[i].second) - a.begin(); ans += rSum.query(qLeft, qRight); rSum.update(qRight, 1); } printf ( "%lld\n" , ans); } return 0; } |
'알고리즘 문제 풀이' 카테고리의 다른 글
777E Hanoi Factory (0) | 2017.03.02 |
---|---|
777D Cloud of Hashtags (0) | 2017.03.01 |
777C Alyona and Spreadsheet (0) | 2017.03.01 |
BOJ 1034 램프 (0) | 2017.02.28 |
BOJ 3117 YouTube (0) | 2017.02.14 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- BFS
- Heap
- tree
- Segment Tree
- Strings
- pattern matching
- suffix array
- Minimum Spanning Tree
- divide and conquer
- parametric search
- branch and bound
- sliding window
- math
- Graph
- greedy
- implementation
- constructive algorithms
- Data structure
- kmp search
- Square root decomposition
- karatsuba
- Fenwick Tree
- sort
- search
- Binary search
- Dynamic Programming
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함