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();
    }
}
posted @ 2025-06-06 22:14  cbbdhz  阅读(20)  评论(0)    收藏  举报