题目链接:https://cn.vjudge.net/problem/UVALive-4329
思路:找出i位置前面技能值小于a[i]的人的个数c1,前面大于a[i]的人的个数就等于n-i-c1。再找出i位置后面小于a[i]的人的个数c2,后面小于a[i]的人的个数为i-c2-1。这个位置的人当裁判就有 c1(n-i-c2)+c2(i-c1-1)种情况。找出每个位置的情况相加为答案。用树状数组记录一下前缀和。
#include<algorithm>
#include<string.h>
#include<stdio.h>
using namespace std;
int t,n;
int a[20010],t1[100010],t2[100010];
int lowbit(int x)
{
return x&-x;
}
int add(int *A,int i,int x)
{
while(i<=100010)
{
A[i]+=x;
i+=lowbit(i);
}
}
long long sum(int *A,int i)
{
long long ans=0;
while(i>0)
{
ans+=A[i];
i-=lowbit(i);
}
return ans;
}
void init()
{
memset(t1,0,sizeof(t1));
memset(t2,0,sizeof(t2));
}
int main()
{
scanf("%d",&t);
while(t--)
{
init();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
add(t2,a[i],1);
}
long long ans=0;
for(int i=1;i<=n;i++)
{
long long c1,c2;
c1=sum(t1,a[i]);
add(t1,a[i],1);
add(t2,a[i],-1);
c2=sum(t2,a[i]);
ans+=c1*(n-i-c2)+c2*(i-c1-1);
}
printf("%lld\n",ans);
}
}