C. Tenzing and Balls

https://codeforces.com/problemset/problem/1842/C

题意:给定n个数,现在要按照规则删除数组中的数,问最多能删多少?规则:i < j且a[i] == a[j],那么可以删除[i, j]区间的所有数。

思路:区间dp,dp[i]代表区间[1, i]内,删完数字后剩下的数字的最小数量。dp[i] = min(dp[i - 1] + 1, rec[a[i]]),其中rec[a[i]]表示如果a[i]作为区间左端点被删除后,[1, i]区间内剩余其他数字的最小数量。 最后答案就是n - dp[n - 1],其中dp[0] = 1, rec[a[0]] = 0(0-indexed)。

总结:这种问题,从全局来思考,每个数字只有作为左端点,在区间内,或者右端点,或者不删除这几种情况。考虑最后一个位置n,如果不删除,则[1, n]少删除一个数,则剩下的数多一个,说明dp[n] = dp[n - 1] + 1。如果删除,那么要找到之前a[n]出现的位置m,并且我们还要知道dp[m - 1],也就是如果位置n要被删除,那么应该是dp[n] = dp[m - 1],因为[m, n]的数都被删了。但是如果一个数字出现了多次,我们就不能精确的找到m,所以我们干脆维护每个数字作为左端点时,前面剩余没被删的数的最小值,就是dp[m - 1]了。。。今日脾气暴躁

inline void solve() {
    int n;
    cin >> n;

    vector<int> a(n);
    for (auto& x : a) {
        cin >> x;
    }    

    vector<int> dp(n);
    vector<int> rec(n + 1, 0x3f3f3f3f);
    dp[0] = 1;
    rec[a[0]] = 0;
    for (int i = 1; i < n; ++i) {
        dp[i] = min(dp[i - 1] + 1, rec[a[i]]);
        rec[a[i]] = min(rec[a[i]], dp[i - 1]);
    }

    cout << n - dp[n - 1] << '\n';
}
posted @ 2025-10-25 15:54  _Yxc  阅读(6)  评论(0)    收藏  举报