「ALFR Round 3」B Swap & Delete 题解
Christmas_Defunct · · 题解
很简单的分类讨论题,赛时 AC 了。
题意简化
你可以对序列
- 交换
a_i 和a_j ,其中i\not=j 。 - 删除
a_i\sim a_j ,但是必须满足a_i=a_j 。
显然的,有
解法
这题求
这时候问题聚焦于另一个地方:如何使操作
注意到
这里,我们只需要分析
- 若
a_1=a_n ,进行1 次操作2 即可,\min k=1 。- 若
a_1\not=a_n ,继续分类讨论。记
b_{a_{i}} 为a_i 在序列中出现的次数。
- 若
b_{a_1}\geq2 ,记另外任意一个值为a_1 且在a 中出现的数的位置为pos_l ,进行一次操作1 ,交换a_{pos_l} 和 a_{n} ,随即转换为a_1=a_n ,故\min k=2 。- 若
b_{a_n}\geq2 ,记另外任意一个值为a_n 且在a 中出现的数的位置为pos_r ,进行一次操作1 ,交换a_{pos_r} 和 a_{1} ,随即转换为a_1=a_n ,故\min k=2 。- 若不满足
b_{a_1}\geq2 和b_{a_n}\geq2 但是\exist\ b_{a_i}\ge2 ,此时记pos_l 和pos_r 为其中相异的两个值为a_i 的数的下标,进行2 次操作1 ,分别交换a_1,a_{pos_l} 和a_n,a_{pos_r} ,随即转换为a_1=a_n ,故\min k=3 。- 若
\forall\ b_{a_i}=1 ,则无论如何进行多少次操作1 都无法转化为a_1=a_n ,此时只能使i=j ,必定满足a_i=a_j ,有n 个数,所以此时\min k=n 。
这样,我们便完成了分类讨论,下面进行整理。
整理得
- 若
a_1=a_n ,\min k=1 ; - 若
b_{a_1}\geq2 或b_{a_n}\geq2 ,\min k=2 ; - 若
\exist\ b_{a_i}\geq2(i\not=1,n) ,则\min k=3 ; - 否则
\min k=n 。
这里的
注意到 map 进行优化即可,此处不再赘述 map 的使用方法,不会用的可以参考别的文章。
综上,我们的每个过程复杂度变化如下:
- 时间复杂度:
\mathcal{O}(n^2)\to\mathcal{O}(n)\to\mathcal{O}(n) 。 - 空间复杂度:
\mathcal{O}(n)\to\mathcal{O(\max a)}\to\mathcal{O}(n) 。
代码
下面是本题的代码,请勿抄袭,这么简单的题目咱还是别抄了。
#include <bits/stdc++.h>
using namespace std;
void work() {
int n, a[100005];
bool flag = false;
cin >> n;
map<int, int> mp;
memset(a, 0, sizeof a);
for (int i = 1; i <= n; i++) {
cin >> a[i];
mp[a[i]]++;
if (mp[a[i]] == 2) flag = true;
}
if (mp[a[1]] >= 2 || mp[a[n]] >= 2) {
if (a[1] == a[n]) cout << 1 << '\n';
else cout << 2 << '\n';
} else if (mp[a[1]] == 1 && mp[a[n]] == 1) {
if (flag) cout << 3 << '\n';
else cout << n << '\n';
}
}
signed main() {
int t;
cin >> t;
while (t--) work();
return 0;
}
此文是本人的第