题目大意:有n个乒乓球队员,每个队员有相应的能力值.现在要由三个人组成比赛,组成比赛的规则是三个人,中间那个人的能力值要在旁边的两个人的能力值之间,问有多少种组队方法
解题思路:二叉索引树,一个数组正序记录前面有多少个人能力值比当前这个人的能力值小,另一个数组记录后面有多少个人能力值比当前这个人的能力值小,然后用乘法规则
#include<cstdio>
#include<cstring>
#define maxn 20010
#define MAX 100010
int C[MAX],A[maxn], B[maxn], num[maxn], N;
int lowbit(int x) {
return x & (-x);
}
long long sum(int x) {
long long ret = 0;
while(x > 0) {
ret += C[x];
x -= lowbit(x);
}
return ret;
}
void add(int x, int d) {
while(x < MAX) {
C[x] += d;
x += lowbit(x);
}
}
int main() {
int test, N, x;
scanf("%d", &test);
while(test--) {
scanf("%d", &N);
memset(C,0,sizeof(C));
for(int i = 0; i < N; i++) {
scanf("%d", &num[i]);
add(num[i],1);
A[i] = sum(num[i]) - 1;
}
memset(C,0,sizeof(C));
for(int i = N - 1; i >= 0; i--) {
add(num[i],1);
B[i] = sum(num[i]) - 1;
}
long long ans = 0;
for(int i = 1; i < N - 1; i++)
ans += (A[i] * (N - i - 1 - B[i])) + (i - A[i]) * B[i];
printf("%lld\n",ans);
}
return 0;
}