1. 程式人生 > >CodeForces 946G Almost Increasing Array(dp)

CodeForces 946G Almost Increasing Array(dp)

G. Almost Increasing Array time limit per test:3 seconds memory limit per test:512 megabytes input:standard input output:standard output

We call an array almost increasing if we can erase not more than one element from it so that the array becomes strictly increasing (that is, every element is striclty greater than every element before it).

You are given an array a consisting of n elements. You are allowed to replace any element with any integer number (and you may do so any number of times you need). What is the minimum number of replacements you have to perform in order to make the array almost increasing

?

Input

The first line contains one integer n (2 ≤ n ≤ 200000) — the number of elements in a.

The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109) — the array a.

Output

Print the minimum number of replaces you have to perform so that a is almost increasing.

Examples Input Copy
5
5 4 3 2 1
Output
3
Input Copy
5
1 2 8 9 5
Output
0
        LIS的題目見多了,但沒發現自己連這麼一個淺顯的套路都不知道……         大致題意:給你一個序列,然後問你最少替換幾個數字可以使得這個序列變成Almost Increasing Array。這個序列可以,刪除其中一個數字可以變成一個嚴格遞增的序列。         首先是考慮簡化問題。如果不考慮刪除數字和嚴格,也即把一個序列替換成不下降的序列最少替換個數。這個問題很顯然,用n-LIS即可。再進一步,如果要求嚴格遞增呢?這就是一個在此之前居然不知道的經典套路:首先把每個數字減去其對應位權,然後再求n-LIS即可,即序列變成{ai-i}。道理也很容易理解。最後,再考慮一下,如果可以刪除一個數字。相當於是,以被刪除的數字作為分解點,之前是上一個問題,每個數字減去位權;之後是減去位權再加一。即,假設刪除ak,那麼在k之前的序列是{ai-i},之後是{ai-i+1}。         如此一來,最終問題,還是LIS問題。我們可以考慮改一下dp,用f[]和g[]表示k之前和k之後的LIS。g可以從f轉移過來,二分的優化仍然成立。具體見程式碼:
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define LL long long
#define N 1000010

using namespace std;

int g[N],f[N],a[N],n;

int main()
{
    cin>>n;
    memset(g,INF,sizeof(g));
    memset(f,INF,sizeof(f));
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    int pos,ans=0;
    for(int i=2;i<=n;i++)
    {
        pos=upper_bound(g+1,g+1+n,a[i]-i+1)-g; g[pos]=a[i]-i+1; ans=max(ans,pos);
        pos=upper_bound(f+1,f+1+n,a[i-1]-i+1)-f; f[pos]=a[i-1]-i+1; g[pos]=min(g[pos],f[pos]); ans=max(ans,pos);
    }
    printf("%d\n",n-1-ans);
    return 0;
}