/*
结果肯定和 逆序对数量有关,假设当前求第k个答案:
如果1-k元素连续,则只要求出1-k的逆序对个数即可
如果不连续,那么先把这k个元素移动到一起,然后再求逆序对
移动的策略是二分找中间位置p,p左边的元素数量=p右边的元素数量
所以用线段树去维护当前已经存在的点位置
每次求答案:二分找位置p,求最小移动代价,求逆序对
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 200005
int n;
struct Node{
int pos,v;
}p[N];
int cmp(Node &a, Node & b){return a.v<b.v;}
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
ll sum1[N<<2],sum2[N<<2];
void update(int pos,int l,int r,int rt){
if(l==r){sum1[rt]=1;sum2[rt]=l;return;}
int m=l+r>>1;
if(pos<=m)update(pos,lson);
else update(pos,rson);
sum1[rt]=sum1[rt<<1]+sum1[rt<<1|1];
sum2[rt]=sum2[rt<<1]+sum2[rt<<1|1];
}
ll query1(int L,int R,int l,int r,int rt){
if(L>R)return 0;
if(L<=l && R>=r)return sum1[rt];
int m=l+r>>1;
ll res=0;
if(L<=m)res+=query1(L,R,lson);
if(R>m)res+=query1(L,R,rson);
return res;
}
ll query2(int L,int R,int l,int r,int rt){
if(L>R)return 0;
if(L<=l && R>=r)return sum2[rt];
int m=l+r>>1;
ll res=0;
if(L<=m)res+=query2(L,R,lson);
if(R>m)res+=query2(L,R,rson);
return res;
}
int query(int k,int l,int r,int rt){
if(l==r)return l;
int m=l+r>>1;
if(k<=sum1[rt<<1])return query(k,lson);
else return query(k-sum1[rt<<1],rson);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)scanf("%d",&p[i].v),p[i].pos=i;
sort(p+1,p+1+n,cmp);
ll rev=0;
for(int i=1;i<=n;i++){
update(p[i].pos,1,n,1);
//二分找到第一个中点
int ans=query(i/2+i%2,1,n,1);
ll Sum1=query2(1,ans-1,1,n,1);//ans前面的和
ll Sum2=query2(ans+1,n,1,n,1);//ans后面的和
ll cnt1=query1(1,ans-1,1,n,1);//ans前面个数
ll cnt2=query1(ans+1,n,1,n,1);//ans后面个数
ll cost=(Sum2-ans*cnt2)+(ans*cnt1-Sum1);
if (cnt2)cost-=cnt2*(cnt2+1)/2;
if (cnt1)cost-=(cnt1+1)*cnt1/2;
rev+=query1(p[i].pos+1,n,1,n,1);
cout<<cost+rev<<" ";
}
puts("");
}