题目 | Cheating Amidakuji
TOYOTA SYSTEMS Programming Contest 2022(AtCoder Beginner Contest 279)
E - Cheating Amidakuji
https://atcoder.jp/contests/abc279/tasks/abc279_e
Problem Statement
You are given a sequence of length
- There is a sequence
. Initially, we have for each . Let us perform the following operation for in this order (in other words, for integers between and except in ascending order). - After all the operations, let
be the value of such that . Find .
Constraints
- All values in the input are integers.
Input
The input is given from Standard Input in the following format:
Output
Print
Sample Input 1
5 4
1 2 3 2
Sample Output 1
1
3
2
4
For
- Initially,
. - Perform the operation for
. That is, swap the values of and , making . - Perform the operation for
. That is, swap the values of and , making . - Perform the operation for
. That is, swap the values of and , making .
After all the operations, we have
Similarly, we have the following.
- For
: performing the operation for in this order makes , so . - For
: performing the operation for in this order makes , so . - For
: performing the operation for in this order makes , so .
Sample Input 2
3 3
2 2 2
Sample Output 2
1
1
1
Sample Input 3
10 10
1 1 1 9 4 4 2 1 3 3
Sample Output 3
2
2
2
3
3
3
1
3
4
4
题解
简化版问题
我们先不考虑被跳过的那个
这个问题非常简单就能想到结果。不妨设这次操作将要交换第
: 会与其后面的那个数交换,即 增大 . : 会与其前面的那个数交换,即 减小 .- 其他情况 : 交换操作与
无关,即 的大小不变。
由此,我们就能在
将原问题拆分
原问题问的是
- 进行
操作后, 目前所在的位置。这个问题就是上文的问题,我们可以在 时间内取得结果,即 . 目前在 位置,再经过 这些操作后, 的新位置在哪?
下面我们再解决第二个问题,整道题目就做出来了。
如何快速求得每个数经过操作后的新位置
这个问题有一个巧妙地思路,我们初始化数列的数值等于其下标,如
为了能够实现递推,减少复杂度,我们是反向进行操作的,最后记得把答案再倒过来输出就行。(对应下方代码 C 部分)
代码
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int N, M;
cin >> N >> M;
vector<int> A(M + 1);
for (int i = 1; i <= M; i++)
cin >> A[i];
/* Part A */
vector<int> pos(M + 1);
pos[0] = 1;
for (int i = 1; i <= M; i++)
{
if (A[i] == pos[i - 1])
pos[i] = pos[i - 1] + 1;
else if (A[i] == pos[i - 1] - 1)
pos[i] = pos[i - 1] - 1;
else
pos[i] = pos[i - 1];
}
/* Part B */
vector<int> where(N + 1), ans;
for (int i = 1; i <= N; i++)
where[i] = i;
for (int i = M; i >= 1; i--)
{
ans.push_back(where[pos[i - 1]]);
swap(where[A[i]], where[A[i] + 1]);
}
/* Part C */
for (int i = ans.size() - 1; i >= 0; i--)
cout << ans[i] << endl;
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi