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; }
编辑器加载中...