配列変更「NOIP以上の2019の学校の入学試験を。」

説明[タイトル]
整数の配列を指定して、\(\) あなたはどちらか任意の数に正の整数を変え、そして最終的には、アレイ全体が厳密に増加し、正の整数であるされますすることができます。Q.少なくとも、あなたはいくつかの数字を変更する必要がありますか?

[入力形式
\(1 \)行:番号\(N \)配列の長さを表し(\(1 \のLeq N \のLeq 100000 \)を)。
\(2 \) \(N + 1 \)ライン:各行\(1 \)配列要素に対応する番号。\(0 \のLeq A [I] \ ^ 9のLeq 10 \) )。

[]出力形式の
アレイ全体が厳密に増加するように出力が変更のいくつかの数の最小値を必要とします。

問題の解決策
のタイトルは「最終的には、アレイ全体が低下していないになり、」善意の多くがあるようですに変更された場合は
、厳密代わりに配列の配列を増やす代わりに落下することは、それぞれに非常に簡単です\([I] \)になり\ ([I] -i \)線上

この処理後のアレイの元のタイトルは、最小変更配列のいくつかの数をドロップしないように変更されて処理になり
、その最長の要求はシーケンスをドロップして、行上の他の番号を取り除くない
LISが求めていないのだろうか?こちらをクリック

コード

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;

ll n;
ll a[100005], b[100005], sz;
ll num[100005], len;
ll maxn;

ll read() {
    ll ret = 0, flag = 1;
    char ch = getchar();
    while (ch > '9' || ch < '0') {
        if (ch == '-') flag = -1;
        ch = getchar();
    }
    while (ch <= '9' && ch >= '0') {
        ret = (ret << 3) + (ret << 1) + (ch ^ '0');
        ch = getchar();
    }
    return ret * flag;
}

ll search(ll x) {
    ll l = 1, r = sz, mid, ret = 0;
    while (l <= r) {
        mid = (l + r) >> 1;
        if (b[mid] > x) {
            ret = mid;
            r = mid - 1;
        } else {
            l = mid + 1;
        }
    }
    return ret;
}

int main() {
    n = read();
    for (int i = 1; i <= n; i++) {
        a[i] = read() - i;
    }
    for (int i = 1; i <= n; i++) {
        if (a[i] >= 0) num[++len] = a[i];
    }
    for (int i = 1; i <= len; i++) {
        if (num[i] >= b[sz]) b[++sz] = num[i];
        else b[upper_bound(b + 1, b + sz + 1, num[i]) - b] = num[i];
        maxn = max(sz, maxn);
    }
    printf("%lld\n", n - maxn);
    return 0;
}

おすすめ

転載: www.cnblogs.com/ak-dream/p/AK_DREAM16.html