题解:CF1698F Equal Reversal
首先
接着你发先一次操作不会改变相邻数对的集合,即
你从图论的角度考虑是一样的,这两个条件是充分且必要的。
考虑有解的情况,增量构造,假设现在
因为有解,所以
分类讨论,如果存在
否则一定会存在一个区间,包含
然后这个东西的操作次数是一个
:::success[代码]{open}
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e2 + 5;
int T, n, a[N], b[N];
vector<pair<int, int>> ans;
void rev(int l, int r)
{
ans.push_back({l, r});
reverse(a + l, a + r + 1);
return;
}
bool work(int i)
{
for(int j = i; j < n; j++)
{
if(a[j] == b[i] && a[j + 1] == b[i - 1])
{
rev(i - 1, j + 1);
return 1;
}
}
int p = -1;
for(int j = i; j < n; j++)
{
if(a[j] == b[i - 1] && a[j + 1] == b[i])
{
p = j;
break;
}
}
if(p == -1) return 0;
vector<int> pos(n + 1, -1);
for(int j = i - 1; j <= p; j++) pos[a[j]] = j;
int l = -1, r = -1;
for(int j = p + 1; j <= n; j++)
{
if(pos[a[j]] != -1)
{
l = pos[a[j]], r = j;
break;
}
}
if(l == -1) return 0;
rev(l, r);
for(int j = i; j < n; j++)
{
if(a[j] == b[i] && a[j + 1] == b[i - 1])
{
rev(i - 1, j + 1);
return 1;
}
}
return 0;
}
void solve()
{
cin >> n;
ans.clear();
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++) cin >> b[i];
if(a[1] != b[1] || a[n] != b[n])
{
cout << "NO\n";
return;
}
vector<pair<int, int>> pa, pb;
for(int i = 1; i < n; i++)
{
int x = a[i], y = a[i + 1];
if(x > y) swap(x, y);
pa.push_back({x, y});
x = b[i], y = b[i + 1];
if(x > y) swap(x, y);
pb.push_back({x, y});
}
sort(pa.begin(), pa.end());
sort(pb.begin(), pb.end());
if(pa != pb)
{
cout << "NO\n";
return;
}
for(int i = 2; i < n; i++)
{
if(a[i] == b[i]) continue;
if(!work(i))
{
cout << "NO\n";
return;
}
}
for(int i = 1; i <= n; i++)
{
if(a[i] != b[i])
{
cout << "NO\n";
return;
}
}
cout << "YES\n" << ans.size() << "\n";
for(auto [l, r] : ans) cout << l << " " << r << "\n";
return;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
cin >> T;
while(T--) solve();
return 0;
}
:::