bit中存到考慮a[i]爲止,區間上數字的出現的個數,爲的是回來統計[1, a[i] - 1]大小範圍的數
考慮到第i個人做裁判,設從a[1]到a[i - 1]有c[i]個比a[i]小的數,則就有i - 1 - c[i]個比a[i]大的數,
同理設從a[ i + 1]到a[n]有d[i] 個比a[i]小的數,則就有n - i - d[i]個比a[i]大的數
利用乘法原理,則i當裁判有c[i] * (n - i - d[i]) + d[i] * (i - 1 - c[i])種情況
sum用來求大小在[1, a[i] - 1]的數的個數,也就是對在這個範圍內的數的個數進行一次累加和
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
using namespace std;
typedef long long ll;
ll T, n, maxn;
ll a[20005], c[20005], d[20005], bit[100005];
ll max(ll x, ll y) {
return x < y ? y : x;
}
ll lowbit(ll x) {
return x & (-x);
}
void add(ll x, ll y) {
//這裏需要維護的樹狀數組的區間是從x到a[i]的最大值
for (ll i = x; i <= maxn; i += lowbit(i)) { //debug i <= maxn
bit[i] += y;
}
}
ll sum(ll x) {
ll ans = 0;
for (ll i = x; i > 0; i -= lowbit(i)) {
ans += bit[i];
}
return ans;
}
int main()
{
cin >> T;
while (T--) {
scanf("%lld", &n);
maxn = -1;
for (ll i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
maxn = max(maxn, a[i]); //debug
}
memset(bit, 0, sizeof(bit));
for (ll i = 1; i <= n; i++) {
add(a[i], 1);
c[i] = sum(a[i] - 1); //求到i爲止出現過多少個小於a[i]的數
}
//反向同理求出d
memset(bit, 0, sizeof(bit));
for (ll i = n; i >= 1; i--) {
add(a[i], 1);
d[i] = sum(a[i] - 1);
}
ll ans = 0;
//乘法原理求出最終結果
for (ll i = 2; i <= n - 1; i++) {
ans = ans + c[i] * (n - i - d[i]) + d[i] * (i - c[i] - 1);
}
printf("%lld\n", ans);
}
return 0;
}