https://www.acmicpc.net/problem/5419
세그먼트 트리와 좌표압축을 통해서 해결 할 수 있다.
우선 pair< x, y > 형태로 입력을 모두 받은뒤에
x축정렬(같다면 y가 큰것부터)을 시행한다.
X축 정렬을 하고난뒤에는
k번째 좌표에서 k번째와 짝지어질 수 있는 좌표는 (0 ~ k-1) 좌표 중에 있을 것이다.
그 좌표들 중에서 k번째보다 y값이 큰것들이 해당 좌표에서 짝 지을 수 있는 좌표들이 된다.
x의 범위는 정렬을통해 인덱스로 체크 하면 되기때문에 상관 없지만 y의 범위가
(-10e9 ≤ xi, yi ≤ 10e9)
이기 때문에 세그먼트 트리의 노드에 모든 y 값을 담을 수 없다.
그래서 좌표압축을 사용한다.
y만 담겨져 있는 vector를 입력때 하나 더만들어서 y축( 내림차순 ) 으로 입력받은뒤
upper_bound를 통해서 해당 y값이 몇번째로 큰 값인지 index를 확인해서
그 index가 결국 세그먼트의 target node index가 된다.
0~index까지 구간합을 결과값에 더해주면 된다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define MAX_N 75001
int tree[MAX_N * 4];
vector<pair<int, int> > vec;
vector<int> y_vec;
void init_tree(int now, int start, int end) {
if (start > end) return;
if (start == end) {
tree[now] = 0;
return;
}
tree[now] = 0;
int mid = (start + end) / 2;
init_tree(now * 2, start, mid);
init_tree(now * 2 + 1, mid + 1, end);
}
void update_tree(int now, int target, int start, int end) {
if (target > end || target < start) return;
if (start == end) {
tree[now]++;
return;
}
int mid = (start + end) / 2;
update_tree(now * 2, target, start, mid);
update_tree(now * 2 + 1, target, mid + 1, end);
tree[now] = tree[now * 2] + tree[now * 2 + 1];
}
int query(int now, int left, int right, int start, int end) {
if (left > end || right < start) return 0;
if (left <= start && end <= right) {
return tree[now];
}
int mid = (start + end) / 2;
return (
query(now * 2, left, right, start, mid) +
query(now * 2 + 1, left, right, mid + 1, end)
);
}
bool cmp_x_y(pair<int, int> a, pair<int, int> b) {
if (a.first == b.first) return a.second > b.second;
return a.first < b.first;
}
bool cmp_y(int a, int b) {
return a > b;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T; cin >> T;
while (T--) {
int N; cin >> N;
vec.clear();
y_vec.clear();
init_tree(1, 0, N - 1);
for (int i = 0; i < N; i++) {
int x, y; cin >> x >> y;
vec.push_back({ x,y });
y_vec.push_back(y);
}
long long ret = 0;
sort(vec.begin(), vec.end(),cmp_x_y);
sort(y_vec.begin(), y_vec.end(), cmp_y);
for (int i = 0; i < vec.size(); i++) {
int x = vec[i].first, y = vec[i].second;
int index = upper_bound(y_vec.begin(), y_vec.end(), y, cmp_y) - y_vec.begin() - 1;
ret += query(1, 0, index, 0, N - 1);
update_tree(1, index, 0, N - 1);
}
cout << ret << "\n";
}
}