【Codeforces】1658C Shinju and the Lost Permutation 题解


题目大意

$b_i$ 为 $a$ 中前 $i$ 个数的最大值。定义操作:把排列 $a$ 向后移动一位(即原本最后一个数成为第一个数,其它数依次后移)。$c_i$ 为 $a$ 移动 $i-1$ 位后,每次生成的 $b_i$ 数组中不同的数的个数。

现在给定 $c$ 数组,判断是否存在对应的排列 $a$。

原题链接

思路

假设已经移动了 $k$ 次,每次移动后,最后一个数会到第一个,其它数的顺序不变。也就是说:

  • 如果 $a_n < a_1$:新的第一个数不超过当前最大值,$c[k+1] = c[k] + 1$。
  • 如果 $a_n > a_i$:当前最大值可能失效,$c[k+1] < c[k]$。

也就是说,我们只需要判断 $c$ 数组中是否存在 $c[k] > c[k-1] + 1$ 即可。

但是需要注意的是,我们任意向右移动 $c$ 数组,也应该存在相应的 $a$ 数组,即 $c[1] - c[n] \le 1$,我们需要特判一下这个条件。

一种直接做法是,我们不妨直接通过向右移动,把 $1$ 转到第一位,这样显然满足 $c[1] - c[n] < 1$。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <bits/stdc++.h>
using namespace std;

void solve() {
int n; cin >> n;
vector<int> a(n);
for (int &v: a) cin >> v;
if (count(a.begin(), a.end(), 1) != 1) {
cout << "NO\n";
return;
}
int p = find(a.begin(), a.end(), 1) - a.begin();
rotate(a.begin(), a.begin() + p, a.end());
for (int i = 1; i < n; ++i) {
if (a[i] - a[i - 1] > 1) {
cout << "NO\n";
return;
}
}
cout << "YES\n";
}

int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t; cin >> t;
while (t--) solve();
return 0;
}

Author: BY 水蓝
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source BY 水蓝 !
  TOC