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;
}