题面及输入输出格式:
样例:
题目大意:
给出一个数组,我们可以对数字x实施操作。
对数字x实施操作:将数组中所有的x变成0
让我们通过操作来将数组变成一个上升序列(不严格),输出最小实施的操作次数。
分析:如果最后一个数字也就是a[n]变成0了,那么其他的所有的数都需要变成0;也就是说 如果a[i]变成0,那么a[i-1],a[i-2].....a[1]都应该变成0。
如果数组中出现两个相同的数字但是他们不连续,例如 1 2 3 4 5 4 4 6 7 8 .那我们应该把1 2 3 4 5 4 4这一串数字全部变成0.
主要就是这些,更多细节见代码。
#include <bits/stdc++.h> using namespace std; int t, n, k; map<int, int> mp; int a[100100]; int vis[100100]; int main() { cin >> t; while (t--) { memset(vis, 0, sizeof(vis)); //初始化数组 memset(a, 0, sizeof(a)); mp.clear(); cin >> n; int cnt = 0; //代表数字种类数 for (int i = 1; i <= n; i++) { cin >> a[i]; if (!mp[a[i]]) cnt++; mp[a[i]]++; //记录a[i]出现的次数 } if (cnt == 1) //如果只有一种数字,那么不用进行操作 { cout << 0 << endl; continue; } for (int i = n; i >= 2; i--) //如果遇到两个相同的数字中间有其他数的记录下,然后跳出 { if (mp[a[i]] >= 2) { if (a[i - 1] == a[i]) mp[a[i]]--; else { vis[a[i]] = 1; break; } } } int zy = 0; //代表不用删除的数字种类数 int flagg = 0; for (int i = n; i >= 1; i--) //把记录之前的所有数字归零 { if (vis[a[i]]) flagg = 1; if (flagg == 1) vis[a[i]] = 1; } for (int i = n; i >= 1; i--) { if (vis[a[i]]) //vis[a[i]]!=0 说明a[i]应该被变为0 直接跳出 break; else { if (zy == 0) { zy++; continue; } if (a[i] < a[i + 1]) zy++; else if (a[i] > a[i + 1]) break; } } cout << cnt - zy << endl; } return 0; }
萌新纪念第一次a出div2 c题。题解写的不好请多多包涵。