#include<bits/stdc++.h>
#define debu
using namespace std;
typedef long long LL;
const int maxn=2*1e4+50;
const int maxnn=1e5+50;
int a[maxn];
int n,l[maxn],maxx;
int c[maxnn],r[maxn];
inline int lowbit(int x)
{
return x&(-x);
}
void add(int x,int value)
{
for(int i=x; i<=maxx; i+=lowbit(i))
c[i]+=value;
}
int sum(int x)
{
int tmp=0;
for(int i=x; i; i-=lowbit(i))
tmp+=c[i];
return tmp;
}
int main()
{
#ifdef debug
freopen("in.in","r",stdin);
#endif // debug
int t;
scanf("%d",&t);
while(t--)
{
maxx=0;
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
maxx=max(maxx,a[i]);
}
LL ans=0;
memset(c,0,sizeof(c));
for(int i=1; i<=n; i++)
{
l[i]=sum(a[i]-1);
//cout<<i<<" "<<l[i]<<endl;
add(a[i],1);
}
memset(c,0,sizeof(c));
for(int i=n; i>=1; i--)
{
r[i]=sum(a[i]-1);
//cout<<i<<" "<<r[i]<<endl;
add(a[i],1);
}
for(int i=1; i<=n; i++)
{
// cout<<i<<" "<<l[i]<<" "<<r[i]<<endl;
ans+=(long long)l[i]*(n-i-r[i])+(long long)r[i]*(i-1-l[i]);
// cout<<ans<<endl;
}
printf("%lld\n",ans);
}
return 0;
}
题目地址:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2330
题解:对于第i个人,设在1到i-1有l[i]个人小于他则有i-1-l[i]大于他,同理i+1到n有r[i]人小于他,则有n-i-r[i]人大于他。由加法原理和乘法原理,ans=sigma(l[i]*(n-i-r[i])+r[i]*(i-1-l[i]),所以只需求出l[i]与r[i]:从前到后扫描,c[x]==1表示x存在,则l[i]=sigma(c[1],c[2],。。。。,(c[a[i]-1)),每求一次后c[a[i]]置为1,r[i]同理。