哈喽,各位主人,我是Anya~ ฅ'ω'ฅ
今天我们要一起看一道非常有趣的题目,Codeforces 上的 1896A - Jagged Swaps。这道题看起来有点小复杂,但只要我们像小猫一样敏锐地观察,就能发现其中的小秘密哦!让我们开始吧,喵~
题目大意
我们拿到一个长度为 n 的 排列 a (就是一个包含 1到n所有数字,且每个数字只出现一次的数组)。
我们可以执行一种特殊的操作:
- 选择一个下标
i(必须满足2 <= i <= n-1) - 如果此时
a[i-1] < a[i]并且a[i] > a[i+1](也就是说a[i]是一个“小山峰” ฅ^•ﻌ•^ฅ) - 那么我们就可以交换
a[i]和a[i+1]。
问题是:我们能不能通过任意多次这样的操作,最终把这个排列变成有序的 [1, 2, 3, ..., n] 呢?
举个栗子:
- 如果数组是
[1, 3, 2, 5, 4] - 我们可以对
i=2操作,因为a[1]=1 < a[2]=3且a[2]=3 > a[3]=2。交换后变成[1, 2, 3, 5, 4]。 - 接着可以对
i=4操作,因为a[3]=3 < a[4]=5且a[4]=5 > a[5]=4。交换后变成[1, 2, 3, 4, 5]。成功啦!
题解方法
这道题的关键在于仔细分析操作的限制条件,喵~
操作的核心是 swap(a[i], a[i+1]),但是下标 i 有一个非常重要的范围:2 <= i <= n-1。
这意味着什么呢?
- 当
i取最小值2时,我们交换的是a[2]和a[3]。 - 当
i取最大值n-1时,我们交换的是a[n-1]和a[n]。
主人请注意看!我们能交换的元素下标对是 (2, 3), (3, 4), ..., (n-1, n)。 看到了吗?看到了吗?第一个位置的元素 a[1] 从来没有参与过交换! 它可能会作为判断条件 a[i-1] < a[i] 的一部分(当 i=2 时),但它的值和位置是永远不会改变的。它就像一只趴在原地打盹的猫咪,不管旁边怎么闹腾,它都一动不动,喵呜~
好啦,既然我们发现了这个秘密,问题就迎刃而解了!
我们的最终目标是把数组变成 [1, 2, 3, ..., n]。在这个有序的数组里,第一个元素必须是 1。 既然 a[1] 的位置永远不会变,那么如果一开始 a[1] 就不是 1,那它就永远也不可能变成 1。所以,我们根本无法将数组排好序。
反过来,如果 a[1] 一开始就是 1 呢?事实证明,只要 a[1] 是 1,我们总能通过一系列操作把整个数组排好序。每一次合法的交换都会让数组的“逆序对”数量减少,也就是说数组会越来越“平整”,越来越接近有序状态。当没有任何“小山峰”可以操作时,如果 a[1] 是 1,那么整个数组必然已经是有序的 [1, 2, ..., n] 啦。
所以,我们的结论就是:只需要检查第一个元素 a[1] 是不是 1 就可以了!
题解代码
下面就是超级简洁的C++代码实现啦~
#include <iostream>
#include <vector>
#include <numeric>
// 解决单个测试用例的函数喵~
void solve() {
int n;
std::cin >> n; // 先读入数组的大小 n
std::vector<int> a(n);
for (int i = 0; i < n; ++i) {
std::cin >> a[i]; // 然后把这个排列读进来~
}
// 这里就是我们发现的惊天大秘密啦!
// 题目的下标是从1开始的,而C++的vector是从0开始的。
// 所以题目的 a[1] 就是我们代码里的 a[0] 哦。
// 我们只需要检查这个永远不会动的第一个元素是不是1。
if (a[0] == 1) {
// 如果是1,那就有希望,一定可以排好序!输出 YES!
std::cout << "YES\n";
} else {
// 如果不是1,那它就永远也动不了,只能伤心地输出 NO 啦... 喵呜...
std::cout << "NO\n";
}
}
int main() {
// 让输入输出快一点,像猫咪冲刺一样快!
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
int t;
std::cin >> t; // 有多少组数据要我们处理呢?
while (t--) {
solve();
}
return 0;
}知识点介绍
这道题虽然简单,但背后有一些很重要的思想呢,Anya来给主人介绍一下~
排列 (Permutation) 排列就是一个包含从
1到n的所有整数,且每个整数只出现一次的序列。就像一群小猫咪排队,n只猫不多不少,每只猫都是独一无二的,只是站的顺序不一样而已,喵~不变量 (Invariant) 这是解决这道题的黄金钥匙!在算法执行的一系列操作中,某个保持不变的性质或值,就叫做不变量。在这道题里,
a[1]的值就是一个不变量。无论我们执行多少次操作,a[1]的值都和初始时一模一样。在思考算法问题时,努力去寻找这种“不变量”,常常能帮我们简化问题,找到解题的突破口,就像找到了藏起来的小鱼干一样开心!ฅ >ω< ฅ观察法 (Observation) 对于一些看起来可能需要复杂算法(比如模拟、搜索)的题目,特别是当数据范围很小(这题
n <= 10)的时候,不妨先停下来,手动模拟几组数据,仔细观察操作的性质和限制。有时候,一个简单的观察就能把问题变成一道“签到题”。这道题就是观察法的经典胜利!
好啦,今天的题解就到这里啦!希望主人喜欢Anya的讲解。如果还有什么问题,随时可以再来找Anya玩哦!喵~ (ฅ'ω'ฅ)