根据对题目的观察,我们可以发现本题其实可以抽象成正序对和逆序对的个数的题目
这就能让我们联想到使用树状数组来解决问题
另外本题需要离散化,因为数据过大。
我们可以先求取所有情况,减去不合法的情况,也就是所谓的容斥原理,那么那些是不满足的呢?
我们从题目看出他要是四元组,而我们用乘法原理求出的情况,包含很多满足情况的三元组
比如Aa<=Ab==Ad<Ac这种情况只有三元组,而我们在计算中也算过了,所以把这些情况减去即可

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<string>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
const int N=3e5+10;
int a[N];
int n;
int tr[N];
int li[N],ri[N];
int lx[N],rx[N];
vector<int> num;
int find(int x){
return lower_bound(num.begin(),num.end(),x)-num.begin()+1;
}
int lowbit(int x){
return x&-x;
}
void add(int x,int c){
int i;
for(i=x;i<=n;i+=lowbit(i))
tr[i]+=c;
}
int sum(int x){
int ans=0;
for(int i=x;i;i-=lowbit(i))
ans+=tr[i];
return ans;
}
int main(){
int i;
while(cin>>n){
memset(li,0,sizeof li);
memset(ri,0,sizeof ri);
memset(rx,0,sizeof rx);
memset(lx,0,sizeof lx);
memset(tr,0,sizeof tr);
num.clear();
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
num.push_back(a[i]);
}
sort(num.begin(),num.end());
num.erase(unique(num.begin(),num.end()),num.end());
ll ans1=0;
ll ans2=0;
ll ans3=0;
for(i=1;i<=n;i++){
int pos=find(a[i]);
li[i]=sum(pos-1);
lx[i]=sum(n)-sum(pos);
add(pos,1);
}
memset(tr,0,sizeof tr);
for(i=n;i>=1;i--){
int pos=find(a[i]);
ri[i]=sum(pos-1);
rx[i]=sum(n)-sum(pos);
add(pos,1);
}
for(i=1;i<=n;i++){
ans3+=1ll*li[i]*ri[i];
ans3+=1ll*lx[i]*rx[i];
ans3+=1ll*li[i]*lx[i];
ans3+=1ll*rx[i]*ri[i];
ans1+=li[i];
ans2+=ri[i];
}
cout<<ans1*ans2-ans3<<endl;
}
}
来源:https://www.cnblogs.com/ctyakwf/p/12259726.html
