Description
给定一个序列,每次可以对一个数 +1 、 −1 ,问最少的操作次数使得序列严格上升。
Solution
这里提供了一种
O(nlogn)
的做法。
大概就是
fi
是一个斜率非正的单峰函数,要找到最值的位置就是斜率从
−1
变到
0
的时候。
这个 fi 的值只跟几个关键点有关,所以只要维护大小关系即可,就可以用堆来维护了。
#include <bits/stdc++.h>
using namespace std;
inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
template<typename T>
inline void read(T &x) {
static char c; x = 0; int sgn = 0;
for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1;
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
if (sgn) x = -x;
}
priority_queue<int> Q;
int a, n;
long long ans;
int main(void) {
freopen("1.in", "r", stdin);
read(n);
read(a); Q.push(a);
for (int i = 1; i < n; i++) {
read(a); a -= i;
Q.push(a);
if (Q.top() > a) {
ans += Q.top() - a;
Q.pop();
Q.push(a);
}
}
cout << ans << endl;
return 0;
}