(赛时不会真有人直接调用 函数吧)
思路
认真观察就会发现, 等价于求算数组 的逆序对,因为 对于数组 中的任意一个逆序对 都会对 产生 的贡献.
求算数组逆序对的方法有很多,比如 归并排序。然而在本题中,采用归并排序只能求算出原始数组 的逆序对,然而本题不太适用,因为当新增一个元素 时,需要统计原数组 中的大于 的元素个数,记为 ,那么新数组的逆序对增量就是 。总言之,归并排序不方便统计新增元素后的逆序对增量。
正解是采用树状数组或线段树求算数组的逆序对数量,且该数据结构也方便处理更新操作。上述问题属于很经典的问题了,初学者请参考视频 树状数组 P1908 逆序对.
Code
#include <bits/stdc++.h>
using namespace std;
class FenwickTree {
private:
vector<int> tree;
public:
FenwickTree(int size) : tree(size + 2) {} // 防止越界
void update(int idx, int delta) {
while (idx < tree.size()) {
tree[idx] += delta;
idx += idx & -idx;
}
}
int query(int idx) {
int res = 0;
while (idx > 0) {
res += tree[idx];
idx -= idx & -idx;
}
return res;
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, q;
cin >> n >> q;
vector<int> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
vector<int> x_list(q);
for (int i = 0; i < q; ++i) {
cin >> x_list[i];
}
vector<int> all_vals = a;
all_vals.insert(all_vals.end(), x_list.begin(), x_list.end());
sort(all_vals.begin(), all_vals.end(), greater<int>());
auto last = unique(all_vals.begin(), all_vals.end());
all_vals.erase(last, all_vals.end());
FenwickTree ft(all_vals.size());
auto get_rank = [&](int x) {
int pos = lower_bound(all_vals.begin(), all_vals.end(), x, greater<int>()) - all_vals.begin();
return pos + 1;
};
long long total = 0;
for (int num : a) {
int r = get_rank(num);
total += ft.query(r - 1);
ft.update(r, 1);
}
cout << total << '\n';
for (int x : x_list) {
int r = get_rank(x);
total += ft.query(r - 1);
ft.update(r, 1);
cout << total << '\n';
}
return 0;
}