Description


Sonya was unable to think of a story for this problem, so here comes the formal description.

You are given the array containing n positive integers. At one turn you can pick any element and increase or decrease it by 1. The goal is the make the array strictly increasing by making the minimum possible number of operations. You are allowed to change elements in any way, they can become negative or equal to 0.

Input


The first line of the input contains a single integer n (1 ≤ n ≤ 3000) — the length of the array.

Next line contains n integer ai (1 ≤ ai ≤ 109).

Output


Print the minimum number of operation required to make the array strictly increasing.

input

7
2 1 5 11 5 9 11

output

9

input

5
5 4 3 2 1

output

12

hint


In the first sample, the array is going to look as follows:

2 3 5 6 7 9 11

|2 - 2| + |1 - 3| + |5 - 5| + |11 - 6| + |5 - 7| + |9 - 9| + |11 - 11| = 9

And for the second sample:

1 2 3 4 5

|5 - 1| + |4 - 2| + |3 - 3| + |2 - 4| + |1 - 5| = 12

题解


考虑求非严格递增序列的解法,最优方案为造成递减的数字转为已经存在的数字(刚好转成不递减即可)。

如:

1 5 2 3 6 这里 5变成2最优

1 2 3 10 9 这里最优方案为 9变成10

可以设\(f[i][j]\)表示前i个数不超过j的最小代价

\[f[i][j]=min(f[i][j-1],f[i-1][j]+abs(a[i]-j))
\]

根据我们之前的推论,那么可以把j(1~max(a))转为为已经存在的数字,把a数组排序去重之后得到b数组

原方程优化为

\[f[i][j]=min(f[i][j-1],f[i-1][j]+abs(a[i]-b[j]))
\]

已知最坏情况下是将每个数都转成一个相同的数,而这个数在原数组出现过,那么n个数肯定不会超过max(a)

答案为f[n][tot],总的时间复杂度为\(O(n^2)\)

至于原题要求严格的递增序列,可以根据

\(ai<a[j] \Leftrightarrow ai \leq aj-1\)

让每个ai-i即可转为一个新的数组,这个数组变成非严格递增的代价就是原数组变成严格递增的代价。

import java.io.*;
import java.util.*;
public class Main {
static final int N=(int)3000+5;
static final long inf=(long)3e12;
long []a=new long[N];
long []b=new long[N];
long [][]f=new long[N][N];
public void solve() {
Scanner in=new Scanner(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
int n=in.nextInt();
for(int i=1;i<=n;i++){
a[i]=in.nextInt()-i;
b[i]=a[i];
}
Arrays.sort(b,1,n+1);
int tot=1;
for(int i=2;i<=n;i++) {
if(b[i]!=b[tot]) b[++tot]=b[i];
}
for(int i=0;i<=n;i++) {
Arrays.fill(f[i], inf);
f[0][i]=0;
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=tot;j++) {
f[i][j]=Math.min(f[i][j-1], f[i-1][j]+Math.abs(a[i]-b[j]));
}
}
out.println(f[n][tot]);
out.flush();
in.close();out.close();
}
public static void main(String[] args) {
(new Main()).solve();
}
}

存在一种贪心做法,记录之前出现的大数,如果这个大数大于当前数,就把他变成当前数。

对于这个贪心解法,暂时还没想到证明,先记录一下。

import java.io.*;
import java.util.*;
public class Main {
static final int N=(int)3000+5;
static final int inf=(int)1e9;
public void solve() {
Scanner in=new Scanner(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
PriorityQueue<Integer>que=new PriorityQueue<Integer>(new Comparator<Integer>() {
@Override
public int compare(Integer o1,Integer o2) {
if(o1.equals(o2)) return 0;
return o1.compareTo(o2)>0?-1:1;
}
});
int n=in.nextInt();
long ans=0;int x;
for(int i=1;i<=n;i++) {
x=in.nextInt()-i;
que.offer(x);
if(x<que.peek()) {
ans+=que.poll()-x;
que.offer(x);
}
}
out.println(ans);
out.flush();
in.close();out.close();
}
public static void main(String[] args) {
(new Main()).solve();
}
}

最新文章

  1. lunix的查看Tomcat目录下日志的快速操作
  2. Codeforces 260 B. Fedya and Maths
  3. Vim ide for shell development
  4. jQuery 遍历 - slice() 方法
  5. linux下解决端口被占用的问题
  6. HDU 2085 核反应堆 --- 简单递推
  7. ZOJ 3606 Lazy Salesgirl 浙江省第九届省赛
  8. Spark源码分析(二)-SparkContext创建
  9. XCode4中的文本查找和文本替换功能
  10. Windows Server 2008找回密码
  11. Guava学习笔记:EventBus(转)
  12. frame、bounds表示大小和位置的属性以及center、position、anchorPosition
  13. iOS 主题/皮肤之 SakuraKit
  14. javascript改变style样式和css样式
  15. CLOSE_WAIT问题-TCP
  16. InnoSetup 脚本打包及管理员权限设置
  17. shuffle的工作原理
  18. .net 4.0 中的特性总结(四):Tuple类型
  19. 由一个“两次请求”引出的Web服务器跨域请求访问问题的解决方案
  20. js数组添加或删除元素

热门文章

  1. Elasticsearch之入门知识
  2. python学习之调试:
  3. ZOJ Seven-Segment Display 暴力dfs + 剪枝
  4. 渣渣菜鸡为什么要看 ElasticSearch 源码?
  5. SQL注入原理与解决方法代码示例
  6. 登录界面点击登录后如何延迟提示成功的div的显示时间并跳转
  7. MFC技术积累——基于MFC对话框类的那些事儿3
  8. Linux OpenGL 实践篇-13-geometryshader
  9. java.lang.NoClassDefFoundError: org/w3c/dom/ElementTraversal问题解决
  10. URL URI URN的区别