小鱼比可爱
对
于
区
间
[
l
,
r
]
的
逆
序
对
个
数
,
可
能
贡
献
多
次
,
发
现
正
常
求
逆
序
对
的
操
作
是
离
散
化
后
套
树
状
数
组
,
每
个
数
的
贡
献
为
1
,
但
本
题
的
逆
序
对
不
直
贡
献
一
次
,
又
因
为
[
l
,
r
]
会
变
化
,
所
以
不
妨
固
定
一
个
值
(
固
定
r
)
,
在
树
状
数
组
中
每
次
加
的
贡
献
为
(
n
−
i
+
1
)
对于区间[l,r]的逆序对个数,可能贡献多次,发现正常求逆序对的操作是离散化后套树状数组,每个数的贡献为1,但本题的逆序对不直贡献一次,又因为[l,r]会变化,所以不妨固定一个值(固定r),在树状数组中每次加的贡献为(n-i+1)
对于区间[l,r]的逆序对个数,可能贡献多次,发现正常求逆序对的操作是离散化后套树状数组,每个数的贡献为1,但本题的逆序对不直贡献一次,又因为[l,r]会变化,所以不妨固定一个值(固定r),在树状数组中每次加的贡献为(n−i+1)
因为本题的数据大,所以应该用高精或__int128
#include<bits/stdc++.h>
#define ll __int128
using namespace std;
const int N=1000100;
ll n;
ll a[N],b[N];
ll read(){
ll f=1;char c=getchar();ll ans=0;
while('0'>c||'9'<c){ if(c=='-') f*=-1;c=getchar();}
for(;'0'<=c&&c<='9';c=getchar()) ans=(ans<<3)+(ans<<1)+c-'0';
return f*ans;
}
void print(ll x){
if(x>=10){
print(x/10);
}
putchar(x%10+'0');
}
ll lowbit(ll x){return x&(-x);}
ll tree[N];
void add(ll x,ll val){
for(ll s=x;s<=n;s+=lowbit(s)) tree[s]+=val;
}
ll get_ans(ll x){
ll ans=0;
for(ll s=x;s>=1;s-=lowbit(s)) ans+=tree[s];
return ans;
}
int main(){
n=read();
for(ll i=1;i<=n;i++){
a[i]=read();
b[i]=a[i];
}
sort(b+1,b+n+1);
ll lon=unique(b+1,b+n+1)-b-1;
for(ll i=1;i<=n;i++) a[i]=lower_bound(b+1,b+lon+1,a[i])-b;
add(a[n],1);
ll sum=0;
for(ll i=n-1;i>=1;i--){
ll ans=get_ans(a[i]-1);
sum+=ans*i;
add(a[i],n-i+1);
}
print(sum);
}