题目
给定一个长度为(n)的序列,求所有区间的逆序对总和
分析
考虑有序数对((i,j))若为逆序对可以给(i*(n-j+1))个区间做贡献
那只要在插入的时候放入(n-j+1),查询的时候结果乘(i),此题就可以转换为树状数组的经典问题
不过注意要开__int128,如果不想写高精度的话
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
typedef long long lll;
typedef __int128 llll;
const int N=1000011; llll ans;
int n,a[N],b[N],m; lll c[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(llll ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline lll query(int x){
rr lll ans=0;
for (;x;x-=-x&x) ans+=c[x];
return ans;
}
inline void update(int x,int y){
for (;x<=m;x+=-x&x) c[x]+=y;
}
signed main(){
n=iut();
for (rr int i=1;i<=n;++i) b[i]=a[i]=iut();
sort(b+1,b+1+n),m=unique(b+1,b+1+n)-b-1;
for (rr int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+1+m,a[i])-b;
for (rr int i=n;i;--i) ans+=query(a[i]-1)*i,update(a[i],n-i+1);
print(ans);
return 0;
}