理解对了了题意的话应该算是道简单的树状数组。
题目要求裁判不能同时低于两个人,或者同时高于两人。就是求一个长度为3的顺序序列。
这样的话对于第i个数ai,我们可以求出左边比ai大的数lmaxi,右边比ai小的数rmini.相乘再加上反过来左边小右边大的情况就是结果。
#include <iostream>
#include<cstdio>
#include<cstring>
#define maxm 100001
#define clr(A,k) memset(A,(k),sizeof(A))
#define LL long long
using namespace std;
int C[maxm],A[maxm];
int lmin[maxm],rmin[maxm],lmax[maxm],rmax[maxm];
void init(){
for(int i=0;i<maxm;i++){
C[i]=0;
lmin[i]=0;
lmax[i]=0;
rmin[i]=0;
rmax[i]=0;
}
}
int lowbit(int x){
return x&(-x);
}
void update(int pos,int val){
while(pos<=maxm){
C[pos]+=val;
pos+=lowbit(pos);
}
}
int query(int x){
int ret=0;
while(x>0){
ret+=C[x];
x-=lowbit(x);
}
return ret;
}
int main()
{
int T,N;
scanf("%d",&T);
while(T--){
scanf("%d",&N);
for(int i=1;i<=N;i++){
scanf("%d",&A[i]);
}
init();
for(int i=1;i<=N;i++){
update(A[i],1);
int tmp=query(A[i]-1);
lmin[i]=tmp;
lmax[i]=i-tmp-1;//返回左边比A[i]大的数
}
clr(C,0);
for(int i=N,j=1;i>=1;i--,j++){
update(A[i],1);
int tmp=query(A[i]-1);
rmin[i]=tmp;
rmax[i]=j-tmp-1;
}
LL sum=0;
for(int i=1;i<=N;i++){
sum+=lmin[i]*rmax[i]+lmax[i]*rmin[i];
}
printf("%I64d\n",sum);
}
return 0;
}