这里是一些简单思维题的练习集合,主要针对 A B C 做题较慢而总结一些重点题目的思路。本部分的练习原则是如果一段时间内没有思考出有效做法就看题解的方法,并总结思维中的问题 qaq

其中每道题题号 \(\color{green} \circ\) 表明未看题解即通过,而 \(\color{red} \circ\) 则表明参考了题解。

\[\newcommand{\lvert}{\left\vert} \newcommand{\rvert}{\right\vert} \rule{750px}{1px} \]

\(\color{green} \circ\) CF1579B. Shifting Sort

Description

给定一个长度为 \(n\) 的序列 \(\{a_n\}\),每一次你可以选择两个位置 \(l, r\) 和一个数字 \(d\),将 \(a_{l \cdots r}\) 这个子序列循环左移 \(d\) 位,求构造一种不多于 \(n\) 步左移的将排列排成升序的方案。\(t\) 组数据。

数据范围:\(1 \le t \le 1000, 2 \le n \le 50, 1 \le a_i \le 10^9.\)

Solution

本题因为感觉模拟好像比较麻烦而一直不知道如何写,又因为读成右移而一直 WA,最后才解决了问题。

考虑到操作次数不多于 \(n\) 次,故只需考虑枚举排名为 \(i\) 的数并将其移动到正确位置即可。我们只需维护当前枚举到的数应当去的位置并且模拟每次左移即可。这里 \(n\) 很小,离散化直接使用了 map 并且每次暴力寻找排名为 \(i\) 的数的位置。

Code

View on github


\(\color{red} \circ\) CF1592B. Hemose Shopping

Description

给定一个长度为 \(n\) 的序列 \(\{a_n\}\),每一次你可以选择两个位置 \(i, j\),然后交换这两个位置上的数。但是 \(i, j\) 需满足 \(\lvert i - j \rvert \ge x\),其中 \(x\) 已给定。问是否存在一种方案将序列排为升序。\(t\) 组数据。

数据范围:\(1 \le x \le n \le 10^5, \sum n \le 2 \times 10^5, 1 \le t \le 10^5.\)

Solution

本题如果暴力模拟肯定会超时,而如果优化模拟似乎过于麻烦,考虑其他方法。然而因为调试模拟花了过多精力,无力优化,于是直接看了题解。

我们考虑一个位置 \(i\),如果其距离 1 或者 \(n\) 的距离都小于 \(x\),则我们始终无法移动这个数,除非这个数已经到了它该到的位置上,否则显然无解。

我们考虑什么时候这种位置会存在,发现 \(2x \le n\) 时这个位置总是不存在的。而对于 \(2x > n\) 的情况,我们发现 \(a_{n - x + 1}, a_{n - x + 2}, \cdots, a_x\) 是无法移动的。所以如果它们在排序中需要移动位置,则无解。

Code

View on github