题目
题意:给定长度为
n
n
n的数组
a
,
b
a,b
a,b,其中数组
b
b
b是数组
a
a
a的一个排列。数组
a
a
a可以执行以下操作:
- 选择 1 < = l < r < = n 1<=l<r<=n 1<=l<r<=n且 a l = = a r a_l==a_r al==ar,令 a l , a l + 1 . . . , a r − 1 , a r = a l + 1 , . . . , a r , a l a_l,a_{l+1}...,a_{r-1},a_r=a_{l+1},...,a_r,a_l al,al+1...,ar−1,ar=al+1,...,ar,al。
通过以上若干次操作后,问数组 a a a能否转换为 b b b。
思路:每次操作,相当于选择两个相同的元素
a
l
,
a
r
a_l,a_r
al,ar,删除
a
l
a_l
al,并把元素
a
r
a_r
ar复制一次。
考虑逆过来思考这个过程。相当于
b
b
b数组中,选择相等的两个相邻元素
b
i
,
b
i
+
1
b_i,b_{i+1}
bi,bi+1,删除其一,并把另一个元素丢到前面任意位置。问最终
b
b
b能否转化为
a
a
a。
我们从分别用下标 i , j i,j i,j大到小遍历数组 a , b a,b a,b,在遍历过程中存储b中重复的元素 b j b_j bj到 S S S备用;如果 b j = = a i b_j==a_i bj==ai,则检查它们下一个元素;如果 b j ! = a i b_j!=a_i bj!=ai,则看 S S S是否存在元素等于 a i a_i ai,存在则取出,不存在,则说明无解,即 b b b不能转换为 a a a。
在#include <bits/stdc++.h>
using namespace std;
const int maxn = 200010;
int a[maxn], b[maxn];
int n, m;
multiset<int> st;
void solve() {
st.clear();
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%d", &a[i]);
}
for (int i = 0; i < n; ++i) {
scanf("%d", &b[i]);
}
int i = n - 1, j = n - 1;
bool ok = true;
while (i >= 0 && ok) {
while (j && b[j] == b[j-1]) {
st.insert(b[j]);
--j;
}
if (j >= 0 && b[j] == a[i]) {
--i;--j;
} else if (st.find(a[i]) != st.end()){
st.erase(st.find(a[i]));
--i;
} else {
ok = false;
}
}
printf("%s\n", ok ? "YES" : "NO");
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
}