C - Move One Card 解説 by en_translator
The operation in the problem statement can be rephrased as follows:
- Choose a segment \([l,r]\) of \(A\), and apply a left or right cyclic shift to \(A _ l,A _ {l+1},\ldots,A _ r\) by one element.
We will represent an operation by a pair of the segment \([l,r]\) and the direction \(\lbrace\)L\(,\) R\(\rbrace\).
Consider the property satisfied by \([l,r]\) in the operation of making \(A\) equal to \(B\) when the answer is Yes.
If \(A=B\) from the beginning, it is sufficient to set \(l=r\). Now we assume that \(A\ne B\) initially.
Let \(m\) be the smallest \(i\) such that \(A _ i\ne B _ i\), and \(M\) be the largest such \(i\). Unless \(m\in[l,r]\), the value of \(A_m\) does not change, so \(m\in[l,r]\). Likewise, \(M\in[l,r]\), so \([m,M]\subseteq[l,r]\).
Assume that \(l\lt m\) and consider the cases of applying a left or right cyclic shift.
- If a right cyclic shift makes \(A\) equal to \(B\), \(A _ r=B _ l\) and \(A _ i=B _ {i+1}\ (l\le i\lt r)\). By definition of \(m\), \(A _ i=B _ i\ (l\le i\lt m)\), so \(A _ r=B _ l=A _ l=B _ {l+1}=A _ {l+1}=\cdots=A _ {m-2}=B _ {m-1}=A _ {m-1}=B _ m\). Hence, applying a right cyclic shift to \([m,r]\) yields the same sequence.
- If a left cyclic shift makes \(A\) equal to \(B\), \(A _ l=B _ r\) and \(A _ {i+1}=B _ i\ (l\le i\lt r)\). By definition of \(m\), \(A _ i=B _ i\ (l\le i\lt m)\), so \(B _ r=A _ l=B _ l=A _ {l+1}=B _ {l+1}=\cdots=B _ {m-2}=A _ {m-1}=B _ {m-1}=A _ m\). Hence, applying a right cyclic shift to \([m,r]\) yields the same sequence.
Likewise, if \(A\) can be made equal to \(B\) by applying the operation on \([l,r]\) with \(M\lt r\), then \(A\) can be made equal to \(B\) by applying the operation on \([l,M]\).
Therefore, if the answer is Yes, then \(A\) can be made equal to \(B\) by applying the operation on \([m,M]\).
By the discussion above, the answer can be found by the following algorithm:
- While \(A\) and \(B\) are non-empty and the last elements have the same value, remove the last elements from \(A\) and \(B\).
- While \(A\) and \(B\) are non-empty and the first elements have the same value, remove the first elements from \(A\) and \(B\).
- The answer is
Yesif \(A\) and \(B\) are empty, and applying a right or left cyclic shift by one to \(A\) makes it equal to \(B\); otherwise, the answer isNo.
With appropriate implementation, the algorithm runs in \(O(N)\) time.
The following is sample code.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int N;
cin >> N;
vector<int> A(N), B(N);
for (auto&& a : A) cin >> a;
for (auto&& b : B) cin >> b;
// Remove the trailing common elements
while (!A.empty() && A.back() == B.back()) {
A.pop_back();
B.pop_back();
}
// Reverse them
ranges::reverse(A);
ranges::reverse(B);
// Remove the trailing common elements
while (!A.empty() && A.back() == B.back()) {
A.pop_back();
B.pop_back();
}
// If A == B
if (A.empty()) { // Yes
cout << "Yes" << endl;
return 0;
}
// Try left cyclic shift
auto A_lshift = A;
ranges::rotate(A_lshift, begin(A_lshift) + 1);
if (A_lshift == B) {
cout << "Yes" << endl;
return 0;
}
// and right cyclic shift
auto A_rshift = A;
ranges::rotate(A_rshift, end(A_rshift) - 1);
if (A_rshift == B) {
cout << "Yes" << endl;
return 0;
}
cout << "No" << endl;
return 0;
}