先思考这样一个问题,若存在一个逆序对,那么这个逆序对会被多少个子序列包含呢?数组的长度为n,除去逆序对所包含的两个元素外,其余的元素都有存在或者不存在两种选择,由此构成的子序列数量应为2^(n-2)个。
显而易见,最终答案就是逆序对数量乘以 2^(n-2)。
而求逆序对数量有多种实现方法,常见的有并归排序和树状数组。这里我使用的是树状数组。
原数组a,其中元素的最大值为maxa。那么创建一个树状数组c,长度为maxa+1。当我们要统计数组值中小于等于x的元素个数的时候,可以将其分解为若干个区间。以数字7为例,统计数组中小于等于7的元素的个数。那么ans = c[7] + c[6] + c[4]。其中c[4]值为区间[1, 4]的个数,c[6]值为区间[5, 6]的个数,c[7]为区间[7, 7]的个数。
一般的,c[x]值为区间[x - lowbit(k) + 1, x]的个数。我们在写函数query时只要做一个递归即可。
接下来是update函数,也就是向数组a中添加元素x。那么c[x]的值+1,同时x的所有祖先,在数组c中的元素值+1。比如我们要向数组添加元素1。那么c[1]++,c[2]++,c[4]++,c[8]++,以此类推。
将树状数组的函数写好后,接下来将数组a从后往前遍历。每当取得一个元素a[i],查询比a[i]小的数有几个,每有一个都构成一个逆序对。查询完毕后将a[i]加入到数组。
下面是代码。
#include <iostream>
#include <vector>
using namespace std;
const int mod = 1e9 + 7;
vector<int> c;
int lowbit(int x) {
return x & -x;
}
void update(int x) {
while (x < c.size()) {
++c[x];
x += lowbit(x);
}
}
int query(int x) {
int ans = 0;
while (x > 0) {
ans += c[x];
x -= lowbit(x);
}
return ans;
}
int main() {
int n, maxa = 0;
cin >> n;
vector<int> a(n);
for (int& ai : a) {
cin >> ai;
if (maxa < ai) maxa = ai;
}
c.resize(maxa + 1, 0);
long long ans = 0;
for (int i = n - 1; i >= 0; --i) {
ans += query(a[i] - 1);
update(a[i]);
}
for (int i = 2; i < n; ++i) {
ans = (ans + ans) % mod;
}
cout << ans;
}
// 64 位输出请用 printf("%lld")



京公网安备 11010502036488号