Title
Solution
假如
a
,
b
,
c
,
d
a,b,c,d
a,b,c,d可以相等,那么
a
n
s
ans
ans是顺序对和逆序对的乘积。可以减去不合法的的方案数。
l
s
,
l
b
,
r
s
,
r
b
ls,lb,rs,rb
ls,lb,rs,rb指的是比分别左边比
i
i
i小的,大的,右边比
i
i
i小的,大的的数量。
排除以下四种情况:
- a = c a=c a=c
- S d < S a = c < S b S_d<S_{a=c}<S_b Sd<Sa=c<Sb
- ( a = c ) < b , d (a=c)<b,d (a=c)<b,d
- r s ∗ r b rs*rb rs∗rb
- a = d a=d a=d
- S c > S a = d < S b S_c>S_{a=d}<S_b Sc>Sa=d<Sb
- c < ( a = d ) < b c<(a=d)<b c<(a=d)<b
- l b ∗ r b lb*rb lb∗rb
- b = c b=c b=c
- S a < S b = c > S d S_a<S_{b=c}>S_d Sa<Sb=c>Sd
- a < ( a = c ) < d a<(a=c)<d a<(a=c)<d
- l s ∗ r s ls*rs ls∗rs
- b = d b=d b=d
- S a < S b = d < S c S_a<S_{b=d}<S_c Sa<Sb=d<Sc
- a , c < ( b = d ) a,c<(b=d) a,c<(b=d)
- l b ∗ l s lb*ls lb∗ls
以第一和第二种情况举例:
因为弄的比较快,下面可能会有些锅**(注意)**。
第一种
注意下面
r
b
,
r
s
rb,rs
rb,rs换一下位置
第二种
注意下面
(
c
,
b
)
(c,b)
(c,b)改成
(
c
,
d
)
(c,d)
(c,d)
Code
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
#define rep(i,x,y) for(register ll i=x;i<=y;i++)
using namespace std;
ll n,ans,t[100500],a[100500],b[100500],p,q,ls[100005],lb[100005],rs[100005],rb[100005];
inline void add(ll x,ll y){for(;x<=n;x+=x&(-x)) b[x]+=y;}
inline ll ask(ll x){ll q=0; for(;x;x-=x&(-x)) q+=b[x]; return q;}
int main(){
scanf("%lld",&n);
rep(i,1,n) scanf("%lld",&a[i]),t[i]=a[i];
sort(t+1,t+n+1);
int m=unique(t+1,t+n+1)-t-1;
rep(i,1,n) a[i]=lower_bound(t+1,t+m+1,a[i])-t;
rep(i,1,n){
ls[i]=ask(a[i]-1); lb[i]=ask(n)-ask(a[i]); p+=ls[i];
add(a[i],1);
}
memset(b,0,sizeof(b));
for(int i=n;i>=1;i--){
rs[i]=ask(a[i]-1); rb[i]=ask(n)-ask(a[i]); q+=rs[i];
add(a[i],1);
}
ans=p*q;
rep(i,1,n) ans-=ls[i]*rs[i]+rs[i]*rb[i]+rb[i]*lb[i]+lb[i]*ls[i];
printf("%lld",ans);
return 0;
}