题解:CF2031B Penchick and Satay Sticks

Ivan422

2024-11-20 15:36:40

Solution

题目大意:给你一个排列 p,要求你可以通过交换相邻两个数差为 1 的数,让排列变成单调递增的,即对于 i1n 之中时,p_i=i

做法:首先考虑分析哪些数可以互换。当 p_i 可以与 p_{i-1}p_{i+1} 交换时,我们发现,任意一组交换后,剩下的一组都会拆散。我们再考虑,可不可以用超过 2 次交换让 p_i=i。显然我们发现,一个数只能与 p_i-1p_i+1 交换,而一个数 p_{i-1} 通过 p_i 能够连环交换到 i+1 的位置,就必须满足:p_{i-1}p_{i+1} 可以交换,才能在与 p_i 交换完之后再进行交换,p_ip_{i-1} 能交换。当然,在这个问题中,我们假设三个数中每一个数都不满足 p_i\neq i,才会有交换的必要,因为是排列,所以 p_i=p_{i+1},并且由于 p_ip_{i+1} 都能与 p_{i-1} 交换,所以 |p_i-p_{i+1}|=2,这显然不能交换,所以综上所述,操作仅限于相邻两项,所以我们就可以轻松过掉这题了。

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int _,n,a[N];
int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>_;
    while(_--){
        cin>>n;
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=n;i++){
            if(i==a[i])continue;
            if(i<n&&a[i+1]==i&&a[i]==i+1){swap(a[i],a[i+1]);}
            else goto nxt;
        }
        if(true){cout<<"Yes\n";}
        else{nxt:;cout<<"No\n";}
    }
    return 0;
}