数字相邻只需求出逆序对就好,但是 不相邻,那么我们可以将所有的数字移到中间位置(贪心可证明),然后求出每个数字移到中间的代价之和即可,逆序对可以边算边求,每次求出这个数字之前比它小的数字的个数,那么 用这个数字减去个数在减一就是后面的比它小的数字的个数,也就是逆序对要增大的值。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 200000;
int a[200005],pos[200005];
long long sum1[200005],sum2[200005];
void add(long long *sum1, int x,int val){
while(x <= maxn){
sum1[x] += val;
x += x&(-x);
}
}
long long sum(long long *sum1, int pos){
long long res = 0;
while(pos){
res += sum1[pos];
pos -= pos&(-pos);
}
return res;
}
signed main()
{
int n;
cin >> n;
for(int i = 1;i <= n; i ++){
cin >> a[i];
pos[a[i]] = i;
}
int ans1 = 0,ans2 = 0;
for(int i = 1; i <= n; i ++){
ans1 += i - 1 - sum(sum1, pos[i]);
add(sum1, pos[i] , 1);
add(sum2, pos[i], pos[i]);
int l = 1, r = n;
while(l < r){
int mid = l + r + 1>> 1;
if(sum(sum1, mid)*2 <= i){
l = mid;
}
else r = mid - 1;
}
int cnt = sum(sum1, l);
long long sum3 = sum(sum2, l);
ans2 = 0;
ans2 += cnt*l - sum3 - cnt*(cnt - 1)/2;
cnt = i - cnt;
sum3 = sum(sum2, n) - sum(sum2, l);
ans2 += sum3 - cnt*(l + 1) - cnt*(cnt - 1)/2;
cout << ans1+ ans2 << " ";
}
cout << endl;
}