Codeforces Round #779 (Div. 2)
Problem
Input
6
1
1
2
1 2
2
2 2
6
1 2 4 6 3 5
6
2 3 1 2 3 4
3
3 2 1
Output
YES
YES
NO
NO
YES
NO
Solution
- 首先观察可以发现,当且仅当 c 数组中 1 出现的次数为 1时,才可能有解,否则一定无解
- We can rotate the array such that c1=1 (initial state) because we don’t have to construct the permutation, so if there exists a permutation with p1=n, the answer is YES.
这是codeforces英文题解中的解释,下面我进一步解释:-
c数组中1的含义:表示此次cyclic shift之后,p数组中第一个数 p1 = n
-
如果排列的首位是 n, 则一定存在一种排列满足 c 数组,也就是一定有解(充分条件,因为我们只需要判断是否有解即可,无需构造出对应的排列)
-
为什么首位是n的情况下一定有解,以下是构造方法:
One way to build a satisfying permutation: After rotating the array c[], write the numbers 1 to n one-by-one from the position(s) with highest c[i] to lowest c[i]. If there exists multiple positions with the same value, go from the smallest index to the largest.
(我也看不明这个段英文说了个什么。。结合着下面的例子看这段英文就好理解了)
-
This is the sufficient condition(充分条件). It can be shown that, if ci+1 − ci ≤ 1 for all 1 ≤ i < n, then there exists a permutation that satisfies.
-
Code
#define endl "\n"
#define IOS ios::sync_with_stdio(0), cin.tie(0),cout.tie(0)
#define all(a) a.begin(), a.end()
void solve()
{
int n; cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++)
cin >> a[i];
auto x = find(all(a), 1);
if (x == a.end())
{
cout << "NO\n";
return;
}
rotate(a.begin(), x, a.end());
for (int i = 1; i < n; i++)
if (a[i] - a[i - 1] > 1 || a[i] == 1)//翻转之后,首位是1,若后面又出现1,则直接return掉即可。
{
cout << "NO\n";
return;
}
cout << "YES\n";
}
int main()
{
IOS;
int T; cin >> T;
while (T--)
{
solve();
}
return 0;
}