CF1481E 图书整理

1 CF1481E 图书整理

2 题目描述

时间限制 \(2s\) | 空间限制 \(256M\)

One day you wanted to read something, so you went to your bookshelf to grab some book. But when you saw how messy the bookshelf was you decided to clean it up first.

There are \(𝑛\) books standing in a row on the shelf, the 𝑖-th book has color \(𝑎_𝑖\).

You'd like to rearrange the books to make the shelf look beautiful. The shelf is considered beautiful if all books of the same color are next to each other.

In one operation you can take one book from any position on the shelf and move it to the right end of the shelf.

What is the minimum number of operations you need to make the shelf beautiful?

数据范围:\(1≤𝑛≤5\times 10^5\)

3 题解

考虑 \(dp_i\) 表示从 \(i\)\(n\) 最多可以保留多少书。首先,\(dp_i\) 肯定要与 \(dp_{i+1}\) 取最小值。这代表着当前书不保留的情况。其次,如果 \(a_i\) 是所有 \(a_i\) 中的最左端,那么我们可以考虑将 \(i\)\(a_i\) 的右端点 \(r_{a_i}\) 之间的所有非 \(a_i\) 的书都放到后面。这里我们用后缀和 \(cnt_{a_i}\) 记录从 \(i\)\(n\) 之间\(a_i\) 出现过的次数。那么这个时候的转移方程就是 \(dp_i = max(dp_i, cnt_{a_i} + dp_{r_{a_i} +1})\)。如果我们当前书不是所有此类书中的最左端,那么我们如果让当前种类的书保留,一定会有左侧的书需要移动到队尾。此时,我们不能让中间的其他书挡住我们的路,所以我们需要把从 \(i\)\(n\) 的所有不是 \(a_i\) 的书全部都移动到后面。也就是说 \(dp_i = max(dp_i, cnt_{a_i})\)

4 代码(空格警告):

#include <iostream>
using namespace std;
const int N = 5e5+10;
int n;
int dp[N], cnt[N], l[N], r[N], a[N];
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        if (!l[a[i]]) l[a[i]] = i;
        r[a[i]] = i;
    }
    for (int i = n; i >= 1; i--)
    {
        dp[i] = dp[i+1];
        cnt[a[i]]++;
        if (l[a[i]] != i) dp[i] = max(dp[i], cnt[a[i]]);
        else dp[i] = max(dp[i], dp[r[a[i]]+1] + cnt[a[i]]);
    }
    cout << n - dp[1];
    return 0;
}

欢迎关注我的公众号:智子笔记

posted @ 2021-04-14 21:50  David24  阅读(85)  评论(0编辑  收藏  举报