Codeforces 1148E Earth Wind and Fire
分析
必要条件:
① \(\sum_{i=1}^{n} s_i = \sum_{i=1}^{n} t_i\)
预处理:
将 \(s, t\) 从小到大排序。
尝试一
首尾匹配。例子
s = 2, 2, 4, 7, 9
t = 4, 5, 5, 5, 5
4, 2, 4, 7, 7
4, 4, 4, 7, 5
4, 5, 4, 6, 5
4, 5, 5, 5, 5
反例
s = 1, 4, 5, 8
t = 2, 3, 6, 7
key observation:
考虑排好序的 \(s\) 和 \(t\)。
① 要使操作次数尽可能少,每次操作必然使得某个 \(s_i\) 变成某个 \(t_j\) 。
这个我不会证明。
② 不考虑操作次数不超过 \(5n\) 的限制。若有解则一定存在一种操作方法使得石头的相对位置不变。换言之,最后 \(s_1\) 变成 \(t_1\),\(s_2\) 变成 \(t_2\),\(s_3\) 变成 \(t_3\) ……
可以用反证法证明第二个结论。假设存在一开始 \(s_i < s_j\) 而最后 \(s_i > s_j\),那么考虑使 \(s_i < s_j\) 变成 \(s_i > s_j\) 的那次操作,假设这次操作是使 \(s_i\) 变大,则可以把这次操作拆成两个:先把 \(s_i\) 变成 \(s_j\),再把 \(s_j\) 变成 \(s_i\) 的目标值。
于是我们可以把这个问题看成是一种括号匹配问题。
若 \(s_i < t_i\) 则把 \(t_i - s_i\) 看成“左括号”,若 \(s_i > t_i\) 则把 \(s_i - t_i\) 看成“右括号”。
若 \(s_i < t_i\) 则把二元组 \((t_i - s_i, \text{\)s_i$ 原来的下标})$ 放进栈里,遇到“右括号”就将其与栈顶的“左括号”配对,若栈顶的左括号被“耗尽”就将其弹出栈;若栈空了而“右括号”还有剩余则说明无解。