题目大意:有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;
}