codeforces998 Bugged Sort
题目链接:
https://codeforces.com/contest/2060/problem/G
思路:
1.一个最简单的观察就是\(a[i]\)和\(b[i]\)上的两个值是绑死的,两个值最多上下颠倒或者到别的位置上。
但这两个值一定在同一个i位置上。
2.一次交换操作肯定会导致\(2\)次上下颠倒,所以最后交换完成的数组和最开始数组发生上下颠倒的值对
一定是偶数个。
3.首先发现\(1\)肯定要移到最前面,然后如果\(1\)和\(2\)在一起那好说,继续找\(3\)就行了。
如果不是则说明要找有\(2\)的移动到前面。因为\(2\)前面如果不是\(1\),必然不合法。
之后的数也以此类推。
但是这里有一个问题,
直接换过来他可能是这样的
\(1,4\)
\(3,2\)
直接换过来上下不对。
然后这里猜测限制没那么严,直接翻转,然后统计翻转次数\(+1\),而且同时也不考虑移动过来后,谁会移
动到\(2\)原来的位置,直接当作这\(n\)个值对都没填,然后按照值大小的顺序逐一放入表里。
只要保证最后值对的总颠倒次数是偶数,都能通过交换达到这个状态。
然后按照值\(1-2n\)的顺序逐一填就行,
然后填的值对的两个值都要打上标记,
之后遍历有标记的值跳过即可,因为位置已经确定了。
然后移到填的时候要检查和前面已经填的数的关系。如果发现自己颠不颠倒都合法
就当成新的一段。
否则与前面的段绑定,因为一段的开头如果颠倒,这一段全要颠倒,否则会不合法。
然后如果颠倒才能接上前面的,统计总颠倒次数\(+1\)。
如果都不合法,输出\(NO\)就行
最后填完全部,发现总次数为偶数输出\(YES\)。如果是奇数检查段里有没有奇数长度的段,当作整体翻
转这一段也能把总次数变成偶数。如果有输出\(YES\),否则输出\(NO\)。
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=200100;
int ans[N][2];
int a[N],b[N];
int p[N<<1];
void solve(){
int n;cin>>n;
set<int>sss;
for(int i=1;i<=n;i++){
cin>>a[i];sss.insert(a[i]);
}
for(int i=1;i<=n;i++)cin>>b[i];
for(int i=1;i<=n;i++){
p[a[i]]=b[i];
p[b[i]]=a[i];
}
vector<int>vis(2*n+1);
int j=0;vector<int>duan;int len=0;
int sp=0;
for(int i=1;i<=2*n;i++){
if(vis[i])continue;
vis[i]=1;vis[p[i]]=1;
if(sss.find(i)!=sss.end()){//说明是i在上面的
if(ans[j][0]<=i&&ans[j][1]<=p[i]&&ans[j][0]<=p[i]&&ans[j][1]<=i){
duan.push_back(len);len=1;j++;
ans[j][0]=i;ans[j][1]=p[i];
}else if(ans[j][0]<=i&&ans[j][1]<=p[i]){
len++;j++;ans[j][0]=i;ans[j][1]=p[i];
}else if(ans[j][0]<=p[i]&&ans[j][1]<=i){
len++;j++;sp++;ans[j][0]=p[i];ans[j][1]=i;
}else{
cout<<"NO"<<endl;return;
}
}else{
if(ans[j][0]<=i&&ans[j][1]<=p[i]&&ans[j][0]<=p[i]&&ans[j][1]<=i){
duan.push_back(len);len=1;j++;
ans[j][1]=i;ans[j][0]=p[i];
}else if(ans[j][1]<=i&&ans[j][0]<=p[i]){
len++;j++;ans[j][1]=i;ans[j][0]=p[i];
}else if(ans[j][1]<=p[i]&&ans[j][0]<=i){
len++;j++;sp++;ans[j][1]=p[i];ans[j][0]=i;
}else{
cout<<"NO"<<endl;return;
}
}
}duan.push_back(len);
if(sp%2==0){
cout<<"YES"<<endl;
}else if(sp%2==1){
for(auto sb:duan){
if(sb&1){
cout<<"YES"<<endl;return;
}
}
cout<<"NO"<<endl;
}
}
signed main(){
#ifdef ONLINE_JUDGE
#else
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
ios::sync_with_stdio(false);cin.tie(0);
int T;cin>>T;
while(T--){
solve();
}
}

浙公网安备 33010602011771号