退役了之后智商下降严重啊。今天bc死惨了。这比较水的题也是去看了题解才反应过来的。


先把序列改成不降。


然后把原来的序列分成一些段,每段的中位数递增。


  考虑新加入一个ai,如果它比前一段的中位数小,那么就把它和前一段合并,再拿合并之后的段去和再前一段比较一下。其实我也不能证明为啥是这样,只是感觉比较有道理。我肯定是没救了。


中位数的话用可合并的堆来维护比较方便。orz各种神级堆,然后我还是用的左偏树。


以后树要拿指针写所以代码巨长。


#include <cstdio>

#include <cctype>

#include <cstring>

#include <algorithm>


using namespace std;


int _d_;

#define readInt(_x_) { \

int& _s_ = _x_; \

while (!isdigit(_d_ = getchar())); \

_s_ = 0; \

while ((_s_ = _s_ * 10 + _d_ - 48), isdigit(_d_ = getchar())); \

}


#define sof(p) ((p)?(p->s):0)

struct node {

int v, s;

node *ls, *rs;

inline void init(int x) {

v = x;

s = 1;

ls = 0;

rs = 0;

}

inline void update() {

s = sof(ls) + sof(rs) + 1;

if (sof(ls) < sof(rs))

swap(ls, rs);

}

};


typedef long long dint;


#ifdef WIN32

#define lld "%I64d"

#else

#define lld "%lld"

#endif

#define _l (long long int)


const int maxn = 1000009;


int n, st[maxn], ts, a[maxn];

dint ans;

node hn[maxn], *ha[maxn], *hb[maxn];


inline node* haMerge(node* p, node* q) {

if (!p)

return q;

else if (!q)

return p;

else if (p-> v > q-> v) {

p-> rs = haMerge(p-> rs, q);

p-> update();

return p;

}

else {

q-> rs = haMerge(q-> rs, p);

q-> update();

return q;

}

}


inline node* haPop(node* &u) {

node* v = u;

if (u)

u = haMerge(u-> ls, u-> rs);

v-> ls = 0;

v-> rs = 0;

v-> s = 1;

return v;

}


inline node* hbMerge(node* p, node* q) {

if (!p)

return q;

else if (!q)

return p;

else if (p-> v < q-> v) {

p-> rs = hbMerge(p-> rs, q);

p-> update();

return p;

}

else {

q-> rs = hbMerge(q-> rs, p);

q-> update();

return q;

}

}


inline node* hbPop(node* &u) {

node* v = u;

if (u)

u = hbMerge(u-> ls, u-> rs);

return v;

}


void hpUnion(int x, int y) {

ha[x] = haMerge(ha[x], ha[y]);

hb[x] = hbMerge(hb[x], hb[y]);

while (sof(ha[x]) > sof(hb[x]) + 1) {

node* u = haPop(ha[x]);

hb[x] = hbMerge(hb[x], u);

}

while (sof(ha[x]) < sof(hb[x])) {

node* u = hbPop(hb[x]);

ha[x] = haMerge(ha[x], u);

}

}


inline int getMid(int x) {

return ha[x]-> v;

}


int main() {

#ifndef ONLINE_JUDGE

freopen("in.txt", "r", stdin);

#endif


memset(ha, 0, sizeof(ha));

memset(hb, 0, sizeof(hb));

readInt(n);

for (int i = 1; i <= n; ++ i) {

readInt(a[i]);

a[i] -= i;

hn[i]. init(a[i]);

}

ts = 0;

st[0] = 0;

for (int i = 1; i <= n; ++ i) {

++ ts;

st[ts] = i;

ha[ts] = hn + i;

hb[ts] = 0;

while (ts > 1 && getMid(ts) < getMid(ts - 1)) {

hpUnion(ts - 1, ts);

st[-- ts] = i;

}

}

ans = 0;

for (int i = 1; i <= ts; ++ i) {

int m = getMid(i);

for (int j = st[i - 1] + 1; j <= st[i]; ++ j)

ans += abs(_l a[j] - m);

}

printf(lld "\n", ans);

}