这种有点小技巧的题目我都转不过弯,已然GG。考试的时候一直想着如何去算出2个点之间有多少个可以的裁判点,然而完全不好计数。就这样怼了一个半小时,其实转换一下,枚举裁判点,去统计能已该点为裁判点的左右两边的点对有多少,就很简单了,
x1是左边比该点搞的,x2是低的,x3是一样的,y1,y2,y3,则是右边的。
#include<cstdio>
#include<cstring>
#define maxl 100010
int n;
long long a[maxl],x1[maxl],x2[maxl],x3[maxl],y1[maxl],y2[maxl],y3[maxl];
long long b[maxl];
long long ans;
void prework()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
}
long long sum(int i)
{
long long s=0;
while(i)
{
s+=b[i];
i-=i&-i;
}
return s;
}
void add(int i,int x)
{
while(i<maxl)
{
b[i]+=x;
i+=i&-i;
}
}
void mainwork()
{
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++)
{
x1[i]=sum(maxl-1)-sum(a[i]);
x2[i]=sum(a[i]-1);
x3[i]=sum(a[i])-sum(a[i]-1);
add(a[i],1);
}
memset(b,0,sizeof(b));
for(int i=n;i>=1;i--)
{
y1[i]=sum(maxl-1)-sum(a[i]);
y2[i]=sum(a[i]-1);
y3[i]=sum(a[i])-sum(a[i]-1);
add(a[i],1);
}
}
void print()
{
ans=0;
for(int i=1;i<=n;i++)
{
ans+=x1[i]*(y2[i]+y3[i]);
ans+=x2[i]*(y1[i]+y3[i]);
ans+=x3[i]*y3[i];
}
printf("%lld\n",ans);
}
int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}