一道逆序对题
CF1915F
https://codeforces.com/contest/1915/problem/F
先了解什么是逆序对 https://www.luogu.com.cn/problem/P1908 即i < j但a[i] > a[j]的数对。
求解的方法:树状数组求解。
树状数组维护的其实就是一个区间内比他大并且比他先出现的值,每次查询的范围就是在原数组的下标之前。
我们可以先将数组按照第一关键字为值,第二关键字为下标数从大到小排序,一是离散化处理,二是为了让值相同,下标大的先出现,这样在统计的过程中,就不会多统计。
现在回到本题。
手画一下,当一个区间[l, r], [x, y],是完全包含的关系的时候,就是一种合法的情况。先将所有l排序,这时的顺序是l从小到大的顺序,然后对该顺序下的r统计逆序对(这里面的思维有点绕,需要理清楚)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int mod = 998244353, INF = 1 << 30;
const int N = 2e5 + 10;
PII a[N], b[N];
LL c[N];
int n;
int lowbit(int x) {
return x & (-x);
}
void update(int p, LL k) {
for (; p <= n; p += lowbit(p)) {
c[p] += k;
}
}
LL ask(int p) {
LL ans = 0;
while (p) {
ans += c[p];
p -= lowbit(p);
}
return ans;
}
void solve() {
cin >> n;
vector<int> B(n + 1);
for (int i = 1; i <= n; i ++) {
cin >> a[i].first;
a[i].second = i;
cin >> B[i];
c[i] = 0;
}
sort(a + 1, a + 1 + n);
LL ans = 0;
for (int i = 1; i <= n; i ++) {
b[i].first = B[a[i].second];
b[i].second = i;
}
sort(b + 1, b + 1 + n, greater<PII>());
for (int i = 1; i <= n; i ++) {
ans += ask(b[i].second - 1);
update(b[i].second, 1);
}
cout << ans << endl;
}
int main() {
cin.tie(nullptr);
ios::sync_with_stdio(false);
int t = 1;
cin >> t;
while(t --) solve();
return 0;
}