左偏树, 可并堆
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define maxn 1000010
using namespace std;
int n;
struct Node{
int val, l, r, dis;
Node(){dis = l = r = val = 0;}
bool operator<(const Node& k)const{
return val < k.val;
}
};
Node T[maxn];
int merge(int a, int b){
if(a == 0 || b == 0)
return a + b;
if(T[a] < T[b])
swap(a, b);
T[a].r = merge(T[a].r, b);
if(T[T[a].l].dis < T[T[a].r].dis)
swap(T[a].l, T[a].r);
T[a].dis = T[a].r ? T[T[a].r].dis + 1 : 0;
return a;
}
int root[maxn], m, size[maxn];
int main(){
scanf("%d", &n);
T[0].dis = -1;
for(int i = 1; i <= n; i ++){
scanf("%d", &T[i].val);
T[i].val -= i;
root[++ m] = i;
size[m] = 1;
while(m > 1 && T[root[m]].val < T[root[m - 1]].val){
int k = size[m] & size[m - 1] & 1;
root[m - 1] = merge(root[m - 1], root[m]);
if(k)root[m - 1] = merge(T[root[m - 1]].l, T[root[m - 1]].r);
size[m - 1] += size[m];
m --;
}
}
int cur = 1;
long long ans = 0;
for(int i = 1; i <= m; i ++)
for(int j = 1; j <= size[i]; j ++, cur ++)
ans += abs(T[root[i]].val - T[cur].val);
printf("%lld\n", ans);
return 0;
}