题意:
有n个人要进行乒乓球比赛每一个人都一个技术值,每个人出现的次序就是
他们住的位置,现在要求进行一场比赛,三个人,裁判的技术值在两个人的
有n个人要进行乒乓球比赛每一个人都一个技术值,每个人出现的次序就是
他们住的位置,现在要求进行一场比赛,三个人,裁判的技术值在两个人的
中间,位置也在两个人的中间,问一共可以进行这种比赛多少次。
思路:
枚举裁判,用树状数组统计裁判左边比裁判大的 ,也就是逆序数,
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 20000+10
#define ll __int64
struct ln
{
ll v,id;
}in[N];
ll n;
ll a[N];
ll c[N];
ll b[N];
ll cmp(ln x,ln y)
{
return x.v<y.v;
}
ll lowbit(ll x)
{
return x&(-x);
}
void updata(ll t,ll value)
{
for(ll i=t;i<=n;i+=lowbit(i))
{
c[i]+=value;
}
}
ll getSum(ll x)
{
ll tmp=0;
for(ll i=x;i>=1;i-=lowbit(i))
{
tmp+=c[i];
}
return tmp;
}
int main()
{
ll T;
scanf("%I64d",&T);
while(T--)
{
scanf("%I64d",&n);
for(ll i=1;i<=n;i++)
{
scanf("%I64d",&in[i].v);
in[i].id=i;
}
sort(in+1,in+1+n,cmp);
memset(c,0,sizeof(c));
a[in[1].id]=1;
for(ll i=2;i<=n;i++)
{
if(in[i].v!=in[i-1].v)
a[in[i].id]=i;
else
a[in[i].id]=a[in[i-1].id];
}
for(ll i=1;i<=n;i++)
{
updata(a[i],1);
b[i]=getSum(a[i]-1);
}
ll maxn=0;
for(ll i=2;i<n;i++)
{
maxn+=b[i]*(n-a[i]-(i-1-b[i]));
maxn+=(i-1-b[i])*(a[i]-1-b[i]);
}
printf("%I64d\n",maxn);
}
return 0;
}