CF 946g - most increasing array tips LIS DP

Title:

To give you an array, ask how many numbers can be changed at most, which can make it become "almost rising". The meaning of "almost rising" is to delete at most one number and then the array will rise strictly.

Explanation:

If not deleted,

If not strictly ascending, we can use n - LIS (LIS means the longest non descending subsequence).

It's a strict rise. Let's first put a[i] - i, and then n - LIS.

The question now is what to do after deleting a number?

Originally, LIS is the minimum value of the end with dp record length of i,

Now add a record to delete a number and the minimum length is i.

Transfer to the code.

Code:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <bitset>
#include <map>
#include <vector>
#include <stack>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <cmath>
#ifdef LOCAL
#define debug(x) cout<<#x<<" = "<<(x)<<endl;
#else
#define debug(x) 1;
#endif

#define chmax(x,y) x=max(x,y)
#define chmin(x,y) x=min(x,y)
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
#define lowbit(x) x&-x
#define mp make_pair
#define pb push_back
#define fir first
#define sec second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, int> pii;

const ll MOD = 1e9 + 7;
const double eps = 1e-10;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const int MAXN = 2e5 + 5;

int a[MAXN];
int d[2][MAXN];

int main() {
#ifdef LOCAL
    freopen ("input.txt", "r", stdin);
#endif
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        a[i] -= i;
    }
    memset(d, 0x3f, sizeof(d));
    int pre = 0;
    for (int i = 1; i <= n; i++) {
        int pos1 = upper_bound(d[0] + 1, d[0] + 1 + i, a[i]) - d[0];
        int pos2 = upper_bound(d[1] + 1, d[1] + 1 + i, a[i] + 1) - d[1];
        d[1][pre] = min(d[0][pre], d[1][pre]);
        d[1][pos2] = a[i] + 1;
        d[0][pre = pos1] = a[i];
    }
    int pos1 = lower_bound(d[0] + 1, d[0] + 1 + n, INF) - d[0] - 1;
    int pos2 = lower_bound(d[1] + 1, d[1] + 1 + n, INF) - d[1] - 1;
    printf("%d\n", max(0, min(n - pos1, n - 1 - pos2)));
    return 0;
}

 

Posted by capslock118 on Thu, 02 Jan 2020 08:42:55 -0800