POJ3928
/*
采用树状数组加速程序
思路是,分数无关,先排序,把index拿出来。满足条件的的 a b c编号必须是a < b < c或者 a >b > c
所以对编号数组从左到右和从右到左扫描,计算出每个编号左边比自己小的个数,右边比自己大的个数,乘起来就是结果,当然还要加上反的情况。
基本上可以算是O(n)把
*/
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
#define MAXN 100010
#define MAXP 20010
int Bit[MAXN];
int rank[MAXP];
int dx[MAXN];
int Lleft[MAXP],Rright[MAXP];
int T,N;
int lowBit(int x)
{
return x&(-x);
}
void update(int x,int c)
{
for(int i=x;i<=N;i+=lowBit(i))
{
Bit[i]+=c;
}
}
int getsum(int x)
{
int ans = 0;
for(int i=x;i>0;i-=lowBit(i))
{
ans += Bit[i];
}
return ans;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&N);
for(int i=0;i<N;i++)
{
scanf("%d",&rank[i]);
dx[rank[i]] = i;
}
sort(rank,rank+N);
for(int i=0;i<N;i++)
{
rank[i] = dx[rank[i]]+1;
}
//for(int i=0;i<MAXN;++i) Bit[i] = 0;
memset(Bit,0,sizeof(int)*MAXN);
for(int i=0;i<N;++i)
{
Lleft[i] = Rright[i] = 0;
}
for(int i=0;i<N;i++)
{
Lleft[i] = getsum(rank[i]);
update(rank[i],1);
}
//for(int i=0;i<MAXN;++i) Bit[i] = 0;
memset(Bit,0,sizeof(int)*MAXN);
for(int i=N-1;i>=0;--i)
{
Rright[i] = getsum(rank[i]);
update(rank[i],1);
}
long long ans = 0;
for(int i=0;i<N;++i)
{
ans += Lleft[i]*(N-1-i-Rright[i])+(i-Lleft[i])*Rright[i];
}
printf("%lld\n",ans);
}
return 0;
}
编辑器加载中...
浙公网安备 33010602011771号