最长非严格上升子序列的思考 && CF 1437E Make It Increasing

最长严格上升子序列

这就是基础的线性dp了(咱们就不讨论 平方暴力做法了)

int main() {
    IOS; cin >> n;
    rep (i, 1, n) f[i] = 1e9;
    rep (i, 1, n) {
        cin >> a[i];
        int cur = upper_bound(f + 1, f + 1 + n, a[i]) - f;
        cout << a[i] << ' ' << cur << '\n';
        f[cur] = a[i]; umax(ans, cur);
    }
    cout << ans;
    return 0;
}

最少改几个数,可以使 a[i] 非严格上升

那不就是长度减去 非严格上升子序列的长度吗?

int main() {
    IOS; cin >> n;
    rep (i, 1, n) f[i] = 1e9;
    rep (i, 1, n) {
        cin >> a[i];
        int cur = upper_bound(f + 1, f + 1 + n, a[i]) - f;
        cout << a[i] << ' ' << cur << '\n';
        f[cur] = a[i]; umax(ans, cur);
    }
    cout << n - ans;
    return 0;
}

最少改几个数, 可以使得 a[i] 严格上升

想想和上面的联系,严格和非严格 有啥区别?

a[i] < a[i + 1] 和 a[i] <= a[i + 1]

我们认先让 a[i+1] 比 a[i] 小 1 , a[i] < a[i + 1] 不就成了 a[i] <= a[i + 1] 了吗?

(现 a[i+1] = 原 a[i+1] - 1), 每个数都这样, 不就是 a[i] - i 吗?

即 1~n a[i] -= i, 就成了上个问题

int main() {
    IOS; cin >> n;
    rep (i, 1, n) f[i] = 1e9;
    rep (i, 1, n) {
        cin >> a[i]; a[i] -= i;
        int cur = upper_bound(f + 1, f + 1 + n, a[i]) - f;
        cout << a[i] << ' ' << cur << '\n';
        f[cur] = a[i]; umax(ans, cur);
    }
    cout << n - ans;
    return 0;
}

CF 1437E Make It Increasing

主菜来了, 先把不能找出来的直接 return 掉

什么情况不行呢? 首先是不然改的序列存在 a[b[i]] > a[b[i + 1]], 或者不让改的两个数之间放不下 a[b[i+ 1]] - a[b[i]]

然后是怎么处理 不能改的位置 (我就到这步卡住的)

其实我们注意到, 只有被选入 f[i] 才有可能不被修改, 当然 f[ans] 肯定是不会被修改

怎么让 f[i] 也不被修改呢? 每次替换只能替换 当前最近的不能修改的位置之后的数就好了 (没想到这个, 我是sb)

int main() {
    IOS; cin >> n >> m; f[0] = -2e9;
    rep(i, 1, n) cin >> a[i];
    rep(i, 1, m) {
        cin >> b[i]; v[b[i]] = 1;
        if (i == 1) continue;
        if (b[i] < b[i - 1] || a[b[i]] - a[b[i - 1]] < b[i] - b[i - 1])
            cout << -1, exit(0);
    }

    rep(i, 1, n) {
        a[i] -= i;
        if (f[ans] <= a[i]) {
            f[++ans] = a[i];
            if (v[i]) k = ans;
        }
        else {
            int cur = upper_bound(f + 1, f + 1 + ans, a[i]) - f;
            if (cur <= k) continue;
            f[cur] = a[i];
            if (v[i]) k = ans = cur;
        }
    }
    cout << n - ans;
    return 0;
}

相关文章

UITabBarController 是 iOS 中用于管理和显示选项卡界面的一...
UITableView的重用机制避免了频繁创建和销毁单元格的开销,使...
Objective-C中,类的实例变量(instance variables)和属性(...
从内存管理的角度来看,block可以作为方法的传入参数是因为b...
WKWebView 是 iOS 开发中用于显示网页内容的组件,它是在 iO...
OC中常用的多线程编程技术: 1. NSThread NSThread是Objecti...