题解:B4583 [合肥市小学组 2026 T3] 魔法水晶
_initializer_list_ · · 题解
题目传送门
思路
因为每次可以左右操作,那么最优策略显然是把中间连续相同的那一段保留,不然不管你怎么删左右两端的总是没有中间相同那一段长。
设中间保留的段为
- 设
L = l - 1 ,也就是段左边的元素个数; - 设
R = n - r ,总数减去右端点也就是段右边的元素数。
那么最后的最小操作数也就是
::::info[为什么不是
好了,然后用双指针
代码
::::success[AC Code]{open}
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int a[N];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
int ans = 1e9; // 初始化一个极大数,来求最小值
for (int i = 1; i <= n; ++i) {
int j = i;
while (j + 1 <= n && a[j + 1] == a[i]) ++j; // 双指针,也可以用 for 循环写
int L = i - 1; // 把对应的 L,R 算出来
int R = n - j;
ans = min(ans, L + R + min(L, R)); // 计算答案
i = j; // 不重复查找
}
cout << ans;
return 0;
} // 完结撒花
::::
时间复杂度大致为