【题意】求有多少种四个数满足Aa < Ab,Ac > Ad,1 < =a < b < = n ,1 < = c < d < = n
【解题方法】4个数两两不同,1 <= a < b <= n,1 <= c < d <= n,A_a < A_b,A_c > A_d。定义:rg(x)=∣{y∣x<y<=n,Ax<Ay}∣rg(x) = \left | { y | x < y <= n, A_x < A_y } \right |rg(x)=∣{y∣x<y<=n,Ax<Ay}∣lg(x)=∣{y∣1<=y<x,Ax<Ay}∣lg(x) = \left | { y | 1 <= y < x, A_x < A_y } \right |lg(x)=∣{y∣1<=y<x,Ax<Ay}∣rs(x)=∣{y∣x<y<=n,Ax>Ay}∣rs(x) = \left | { y | x < y <= n, A_x > A_y } \right |rs(x)=∣{y∣x<y<=n,Ax>Ay}∣ls(x)=∣{y∣1<=y<x,Ax>Ay}∣ls(x) = \left | { y | 1 <= y < x, A_x > A_y } \right |ls(x)=∣{y∣1<=y<x,A
x>Ay}∣allg=∑i=1nrs(i)allg = \sum_{i=1}^{n}{rs(i)}allg=∑i=1nrs(i)以上都可以通过树状数组在O(n log n)O(n\ log\ n)O(n log n)的时间内求出(需要先对A序列进行离散化处理)。然后,answer=∑a=1nrg(a)∗(allg−lg(a)−rs(a))−∑b=1nls(b)∗(lg(b)+rs(b)answer = \sum_{a=1}^{n}{rg(a) * (allg - lg(a) - rs(a))} - \sum_{b=1}^{n}{ls(b) * (lg(b) + rs(b)}answer=∑a=1nrg(a)∗(allg−lg(a)−rs(a))−∑b=1nls(b)∗(lg(b)+rs(b)
【AC 代码】
#include<bits/stdc++.h>
using namespace std;
const int N =6e5;
#define LL long long
LL sum[N],a[N],x1[N],x2[N],d1[N],d2[N],A[N];
int k;
int lowbit(int x){return x&(-x);}
void update(int x)
{
while(x<k){
sum[x]++;
x+=lowbit(x);
}
}
LL query(int x)
{
LL t=0;
while(x){
t+=sum[x];
x-=lowbit(x);
}
return t;
}
int main()
{
int n;
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++){
scanf("%I64d",&a[i]);
A[i]=a[i];
}
sort(A+1,A+1+n);
k=2;
for(int i=2;i<=n;i++) if(A[i]!=A[i-1]) A[k++]=A[i];
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++){
int pos=lower_bound(A+1,A+k,a[i])-A;
x1[i]=query(pos-1);
d1[i]=query(k-1)-query(pos);
update(pos);
}
memset(sum,0,sizeof(sum));
for(int i=n;i>=1;i--){
int pos=lower_bound(A+1,A+k,a[i])-A;
d2[i]=query(pos-1);
x2[i]=query(k-1)-query(pos);
update(pos);
}
LL ans1=0,ans2=0;
for(int i=1;i<=n;i++){
ans1+=x1[i];
ans2+=d1[i];
}
LL ans=ans1*ans2;
for(int i=1;i<=n;i++){
ans-=x1[i]*d1[i]+x2[i]*d2[i]+x1[i]*d2[i]+x2[i]*d1[i];
}
printf("%I64d\n",ans);
}
return 0;
}