原题链接:点击打开链接
题意:有t组数据,每行数据的第一个数 n 表示有n个人,每个位置上的数据代表选手的技能值,现在要三个人组队,按照位置的顺序,三个人中间的人是裁判,两边的选手,裁判的技能值要跟位置一样位于两位选手之间。
思路:一个点一个点的判断,求该点点左边比它大的数的个数,右边比它小的数的个数,相乘就是一部分的解,再求左边比它小的数的个数,右边比它大的数的个数,相乘得另一部分的解,两部分的解相加就是要求的结果 。
code:
#include<stdio.h>
#include<string.h>
#define MAX 100100
int n,c[MAX],l1[MAX],l2[MAX],r1[MAX],r2[MAX],a[MAX];
int flag;
int Lowbit(int k)
{return (k&-k);}
void update(int pos,int num)
{
while(pos<MAX)//是MAX 而不是 n
{
c[pos]+=num;
pos+=Lowbit(pos);
}
}
int sum(int pos)
{
int s=0;
while(pos>0)
{
s+=c[pos];
pos-=Lowbit(pos);
}
return s;
}
int main()
{
// freopen("i.txt","r",stdin);
int i,t;
scanf("%d",&t);
while(t--)
{
memset(c,0,sizeof(c));
scanf("%d",&n);
for(i=1;i<=n;i++)//求左边比该点技能值大的数的个数,小的数的个数
{
scanf("%d",&a[i]);
l1[i]=sum(a[i]); //输入的i个数中 有 sum(a[i]) 个比a[i]小
l2[i]=i-1-l1[i]; //输入的i个数中 有 i-1-sum(a[i]) 个比a[i]大
update(a[i],1);
}
memset(c,0,sizeof(c));
int j=1;//代表现在输入的数的个数
for(i=n;i>=1;i--,j++)//求右边比该点技能值大的数的个数,小的数的个数
{
r1[i]=sum(a[i]);//输入a[i]后 输入的那些数中有 sum(a[i]) 个比a[i]小的
r2[i]=j-1-r1[i]; //输入a[i]后输入的那些数中有 j-1-sum(a[i] 个比a[i]大的
update(a[i],1);
}
__int64 ans=0;
for(i=1;i<=n;i++)
ans+=l1[i]*r2[i]+l2[i]*r1[i];
printf("%I64d\n",ans);
}
return 0;
}