Codeforces Round #371 (Div. 2)E. Sonya and Problem Wihtout a Legend[DP 離散化 LIS相關]

Candy?發表於2016-09-15
E. Sonya and Problem Wihtout a Legend
time limit per test
5 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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.

Examples
input
7
2 1 5 11 5 9 11
output
9
input
5
5 4 3 2 1
output
12
Note

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

11

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

And for the second sample:

5

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


題意:一個序列加減1變成嚴格單增最少運算元


 

很像LIS,然後就沒時間了

d[i][j]表示前i個以j結尾的最少運算元

d[i][j]=min{d[i-1][k]+a[i]-j:k<=?j}

j離散化 --> m[j]  sort(m)  可以發現最後的一個一定可以是原序列中的值

嚴格單調遞增,直接處理好難我不會(因為那樣的話不一定原序列結尾了,可能+1),網上題解上都是讓a[i]-=i變成不嚴格

可以用mn維護min(d[i-1][k]),少了一層迴圈

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
const int N=3005;
const ll INF=1e19;
int n,k,a[N],m[N];
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
ll d[N][N],ans=INF;
void dp(){
    for(int i=1;i<=n;i++){
        ll mn=INF;
        for(int j=1;j<=k;j++){
            mn=min(mn,d[i-1][j]);
            d[i][j]=mn+abs(a[i]-m[j]);
        }
    }
}

int main(int argc, const char * argv[]) {
    n=read();
    for(int i=1;i<=n;i++) a[i]=m[i]=read()-i;
    sort(m+1,m+1+n);
    k=unique(m+1,m+1+n)-m-1;//printf("k %d\n",k);
    dp();
    for(int i=1;i<=k;i++) ans=min(ans,d[n][i]);
    cout<<ans;
    return 0;
}

 

 

 

相關文章