THUSC2022 D. 造计算机

又被构造杀了。。。

不同轮换的交换位置不会重复,

一个自然的思路是把所有轮换提出来,按长度的奇偶考虑

1.偶环

这种时候可以通过 \(2\) 个寄存器解决。

可以将环上的 \(1,2\) 号元素放入 \(1,2\) 号寄存器

然后将 \(1\) 放在 \(2\) 的位置,将 \(3\) 放入寄存器 \(1\) ,以此类推

2.奇环

\(m=3\) 的构造:

注意到与偶环不同的情况在于最后一个元素没办法换到寄存器上

那么我们再用一个寄存器放最后一个元素即可

\(m=2\) 的构造:

将第 \(n\) 个元素通过寄存器 \(2\) 换到 \(1\) , 注意此时寄存器 \(2\) 内的元素为 \(2\) ,再把第 \(2\) 个元素换到寄存器 \(1\)

然后将寄存器 \(2\) 的元素放在 \(2\) , 将元素 \(3\) 放在寄存器 \(2\) ,以此类推。

最后一步时第 \(n\) 个位置是空的,并且元素在寄存器 \(1\) 中,直接换就可以了。

最后将 \(m\) 个寄存器内部排序即可

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair< int , int >
#define fi first
#define sc second
#define mp make_pair

const int MAXN = 2e5;
int n , m , a[ MAXN + 5 ];
vector< pii > op; vector< int > pos;
queue< int > q; //map< pii , bool > use;

void opt( int u , int v ) {
    // assert( !use[ mp( u , v ) ] );
    op.push_back( mp( u , v ) );
    swap( a[ u ] , a[ v ] ); 
    // use[ mp( u , v ) ] = use[ mp( v,  u ) ] = 1;
}
int main( ) {
    scanf("%d",&n);
    for( int i = 1 ; i <= n ; i ++ ) scanf("%d",&a[ i ]);
    for( int i = n + 1 ; i <= 2 * n ; i ++ ) a[ i ] = i;
    
    int m = 1;
    for( int i = 1 ; i <= n ; i ++ ) if( i != a[ i ] ) {
        int cnt = 1;
        pos.clear(); pos.push_back( i );
        for( int j = a[ i ] ; j != i ; j = a[ j ] ) cnt ++ , pos.push_back( j );

        if( cnt % 2 == 0 ) {
            m = max( m , 2 );
            opt( pos[ 0 ] , n + 1 ); opt( pos[ 1 ] , n + 2 );
            for( int j = 1 ; j < cnt - 1 ; j ++ ) {
                opt( n + 1 + !( j & 1 ) , pos[ j ] );
                opt( pos[ j + 1 ] , n + 1 + !( j & 1 ) );
            }
            opt( n + 1 , pos[ cnt - 1 ] ); opt( n + 2 , pos[ 0 ] );
        }
        if( cnt & 1 ) {
            m = max( m , 2 );
            opt( pos[ cnt - 1 ] , n + 2 ); opt( n + 2 , pos[ 0 ] );
            opt( pos[ 1 ] , n + 1 );
            for( int j = 1 ; j < cnt - 1 ; j ++ ) {
                opt( n + 1 + ( j & 1 ) , pos[ j ] );
                if( j != cnt - 2 ) opt( pos[ j + 1 ] , n + 1 + ( j & 1 ) );
            }
            opt( n + 1 , pos[ cnt - 1 ] );
        }
    }
    if( m == 1 ) return printf("0 0\n") & 0;
    
    for( int i = n + 1 ; i <= 2 * n ; i ++ ) if( a[ i ] != i ) q.push( i );
    while( !q.empty() ) {
        int u = q.front(); q.pop();
        if( u == a[ u ] ) continue;
        opt( u , a[ u ] ); if( u != a[ u ] ) q.push( u );
    }

    // for( int i = 1 ; i <= n + m ; i ++ ) printf("%d ", a[ i ] ); puts("");

    printf("%d %d\n", m , op.size() );
    for( pii v : op ) printf("%d %d\n", v.fi , v.sc );
    return 0;
}
posted @ 2022-03-12 17:12  chihik  阅读(115)  评论(0编辑  收藏  举报