2023.6.16 每日一题

原题链接

B - Technocup 2020 - Elimination Round 1 - D

B. Sequence Sorting - 2000

题目大意

给定一个数组,定义一个操作:选定一个数,将所有值等于这个数的数移动到数组的一端(数组头或者数组尾)。问将数组变成非递减序列最少需要多少操作次数。

解题思路

对于每一种数,我们记录他们第一次出现的位置和最后一次出现的位置来界定他的跨度。

我们使用一个dp数组去找对于每一种元素,他最后一次出现的位置比下一个的第一次出现还要小的情况是否得到满足。

一旦存在满足如上条件的序列,那么这段序列涉及到的元素就不需要移动,求出这样的序列长度的最大值拿总数减去即可。

AC Code

#include <iostream> #include <algorithm> #include <cstring> #define endl '\n' #define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr) using namespace std; typedef long long LL; const int N = 3e5 + 10; const int MOD = 1e9 + 7; LL a[N], fir[N], lst[N]; LL dp[N]; pair<int, pair<int, int>> p[N]; void solve() { int n, cnt = 0; cin >> n; fill(fir + 1, fir + n + 1, 0); fill(lst + 1, lst + n + 1, 0); fill(dp, dp + n + 1, 0); for (int i = 1; i <= n; ++i) { cin >> a[i]; if (!fir[a[i]]) { cnt++; fir[a[i]] = i; } lst[a[i]] = i; } for (int i = 1, j = 0; i <= n; ++i) { if (fir[a[i]] == i) { p[++j] = {a[i], {fir[a[i]], lst[a[i]]}}; } } sort(p + 1, p + cnt + 1); dp[1] = 1; for (int i = 2; i <= cnt; ++i) { dp[i] = (p[i - 1].second.second < p[i].second.first) ? dp[i - 1] + 1 : 1; } cout << cnt - *max_element(dp + 1, dp + cnt + 1) << endl; } signed main() { ios; int T = 1; cin >> T; while (T--) { solve(); } }

__EOF__

本文作者叁纔
本文链接https://www.cnblogs.com/SanCai-Newbie/p/17485920.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   叁纔  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示