题意 一条街上住着一群乒乓球员 每个人的rank都不一样 每两个人可以找一个人做裁判打球 裁判不能比他们rank都低或都高 并且两个人走到裁判家的总路程不能高于两个人的距离
比赛中的三人 任何一个人不同 都是不同的比赛 问最多多少场不同的比赛
也就是说裁判的rank在他们之间 并且家也在两人之间
用树状数组来解答
可知 这条街看作左右向的话 每个人做裁判的场次数相加就是总答案
这个人做裁判的次数=左边比自己弱的人*右边比自己强的人+左边比自己强的人*右边比自己弱的人
由于rank最多是10w 开的下 不用离散化什么的
当输入a[i]的时候(i从1~n)add之前 求一次sum 是这个人左边比自己弱的人
i-1-sum 是这个人左边比自己强的人
然后add
当所有的a[i]都输入并且add完毕后
再对每个a[i]求sum sum-1-这个人左边比自己弱的人=这个人右边比自己弱的人
n-这个人左边比自己弱的人-左边比自己强的人-右边比自己弱的人-1=右边比自己强的人
然后for循环求答案就可以了
需要注意的是最后的ans比较大 int会wa 开long long
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<math.h>
using namespace std;
int c[100050];
int a[100050];
int xiaoyi[100050];
int xiaoer[100050];
int dayi[100050];
int daer[100050];
int n;
int lowbit(int x)
{
return x&(-x);
}
void add(int x)
{
for(int i=x;i<=100000;i+=lowbit(i))
{
c[i]++;
}
}
int sum(int x)
{
int ans=0;
for(int i=x;i>0;i-=lowbit(i))
{
ans+=c[i];
}
return ans;
}
int main(){
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
int xiaoyiyi=sum(a[i]);
xiaoyi[i]=xiaoyiyi;
add(a[i]);
dayi[i]=(i-1-xiaoyiyi);
}
for(int i=1;i<=n;i++)
{
int xiaozong=sum(a[i]);
xiaoer[i]=(xiaozong-1-xiaoyi[i]);
daer[i]=(n-xiaoyi[i]-xiaoer[i]-1-dayi[i]);
}
long long int ans=0;
for(int i=1;i<=n;i++)
{
ans+=(xiaoyi[i]*daer[i]);
ans+=(xiaoer[i]*dayi[i]);
}
printf("%I64d
",ans);
}
}