题目大意
定义
b
i
为
b_i为
bi为一个排列
a
a
a中前
i
i
i个数的最大值。
定义操作:把排列
a
a
a向后移动一位,即,原本最后一个数成为第一个数,原本第一个数成为第二个…
定义
c
i
c_i
ci为向后移动
i
−
1
i-1
i−1位后,每次生成的
b
i
b_i
bi数组中,不同的数的个数。
现在给定 c c c数组,判断是否存在对应的排列 a a a
思路
假设已经移动了 k k k次,每次移动后,最后一个数会到第一个,其它数的顺序不变。也就是说:
- 如果 a n < a 1 a_n < a_1 an<a1,那么 c [ k + 1 ] = c [ k ] + 1 c[k + 1] = c[k] + 1 c[k+1]=c[k]+1。
- 如果 a n > a i a_n > a_i an>ai,那么 c [ k + 1 ] < c [ k ] c[k + 1] < c[k] c[k+1]<c[k]
也就是说,我们只需要判断 c c c数组中是否存在 c [ k ] > c [ k − 1 ] + 1 c[k] > c[k - 1] + 1 c[k]>c[k−1]+1即可。
但是需要注意的是,我们任意向右移动 c c c数组,也应该存在相应的 a a a数组,即 c [ 1 ] − c [ n ] < = 1 c[1] - c[n] <= 1 c[1]−c[n]<=1,我们需要特判一下这个条件。
一种直接做法是,我们不妨直接通过向右移动,把 1 1 1转到第一位,这样显然 c [ 1 ] − c [ n ] < 1 c[1] - c[n] < 1 c[1]−c[n]<1
代码
#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;
}