HDU_2492_Ping pong
摘抄自白书:考虑第i个人当裁判的情形。假设a[1]到a[i-1]有c[i]个比a[i]小,那么就(i-1)-c[i]个比a[i]大;同理,假设a[i+1]到a[n]中有d[i]个比a[i]小,那么就有(n-i)-d[i]个比a[i]大。根据乘法原理和加法原理,i当裁判有c[i]*(n-i-d[i])+(i-c[i]-1)*d[i]种比赛。这样,问题就转发为c[i]和d[i]。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<string> #include<queue> using namespace std; #define N 100005 #define LL long long int c[N],a[N],lmin[N],lmax[N],rmin[N],rmax[N]; int sum(int x) { int ret=0; while(x) { ret+=c[x]; x-=x&-x; } return ret; } void add(int x) { while(x<=N) { c[x]++; x+=x&-x; } } int main() { int t,i,j,k,n; scanf("%d",&t); while(t--) { memset(c,0,sizeof(c)); scanf("%d",&n); for(i=1;i<=n;++i) scanf("%d",&a[i]); for(i=1;i<=n;++i) { add(a[i]); lmin[i]=sum(a[i]-1); lmax[i]=i-1-lmin[i]; } memset(c,0,sizeof(c)); for(i=n,j=1;i>0;--i,++j) { add(a[i]); rmin[i]=sum(a[i]-1); rmax[i]=j-1-rmin[i]; } LL ans=0; for(i=1;i<=n;++i) { ans+=lmin[i]*rmax[i]+rmin[i]*lmax[i]; } printf("%I64d\n",ans); } return 0; }