题目:
题目分析:要保证两对数满足前面的大于后面的,第一对数的下标中较大的小于第二对数中下标较大的,那么我们可以利用前缀和和后缀和的思想,先预处理算出每一个数的前缀中比它小的数的个数,再计算出后缀中比它大的个数,利用树状数组可以快速求取,然后对前面的数取前缀和,也就是以它为较大数的所有数对的个数,枚举比它大的数中后缀的个数,相乘就是结果,具体实现详见代码:
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define MAX 100007
using namespace std;
int n;
int c[MAX];
int a[MAX];
int les[MAX];
int more[MAX];
int lowbit ( int x )
{
return x&-x;
}
void add ( int x , int d )
{
while ( x <= n )
{
c[x]+=d;
x += lowbit ( x );
}
}
int sum ( int x )
{
int rt = 0;
while ( x )
{
rt += c[x];
x -= lowbit ( x );
}
return rt;
}
int main ( )
{
int t;
scanf ( "%d" , &t );
while ( t-- )
{
scanf ( "%d" , &n );
for ( int i = 1 ; i <= n ; i++ ) scanf ( "%d" ,&a[i] );
memset ( c , 0 , sizeof ( c ) );
for ( int i = 1 ; i <= n ; i++ )
{
les[i] = sum ( a[i] );
add ( a[i], 1 );
}
memset ( c , 0 , sizeof (c ) );
for ( int i = n ; i >= 1 ; i-- )
{
more[i] = sum(n)-sum ( a[i] );
add ( a[i],1 );
}
memset ( c , 0 , sizeof ( c ) );
long long ans = 0;
long long sum = 0;
for ( int i = 1 ; i <= n ; i++ )
{
ans += sum*more[i];
sum += les[i];
}
printf ( "%lld\n" , ans );
}
}