Codeforces 1491G - Switch and Flip(构造题)

Codeforces 题目传送门 & 洛谷题目传送门

obviously,难度高一点的构造题对我来说都是不可做题

首先考虑将排列拆成一个个置换环,也就是 \(\forall i\) 连边 \(i\to p_i\),显然这样我们可以得到一个个环。

首先考虑怎样同时处理两个置换环,假设有两个环,长度分别为 \(p,q\),元素分别为 \(x_1,x_2,\cdots,x_p;y_1,y_2,\cdots,y_q\)。我们考虑以下步骤同时将这两个环中所有元素复位:

  • 交换 \(x_1,y_1\),两个置换环变为 \(-y_1,x_2,\cdots,x_p;-x_1,y_2,\cdots,y_q\)

  • \(\forall i\in[2,q]\),依次交换 \(y_i\) 与原本 \(x_1\) 位置上的数,置换环依次变为:

    • \(-y_2,x_2,x_3,\cdots,x_p;-x_1,y_1,y_3,\cdots,y_q\)
    • \(-y_3,x_2,x_3,\cdots,x_p;-x_1,y_1,y_2,\cdots,y_q\)
    • ……
    • \(-y_q,x_2,x_3,\cdots,x_p;-x_1,y_1,y_2,\cdots,y_{q-1}\)
  • 同理 \(\forall i\in[2,p]\) 交换 \(x_i\) 与原本 \(y_1\) 位置上的数,置换环依次变为:

    • \(-y_q,x_1,x_3,\cdots,x_p;-x_2,y_1,y_2,\cdots,y_{q-1}\)
    • \(-y_q,x_1,x_2,\cdots,x_p;-x_3,y_1,y_2,\cdots,y_{q-1}\)
    • ……
    • \(-y_q,x_1,x_2,\cdots,x_{p-1};-x_p,y_1,y_2,\cdots,y_{q-1}\)
  • 交换 \(x_p,y_q\)(原本 \(x_1,y_1\) 位置上的数),置换环变为 \(x_p,x_1,x_2,\cdots,x_{p-1};y_q,y_1,y_2,\cdots,y_{q-1}\),大功告成

因此我们实现了用 \(p+q\) 次操作同时处理两个置换环,但是显然置换环的个数不一定是偶数,即可能出现剩余一个置换环的情况,故进一步考虑怎样处理最后一个置换环。

还是假设最后一个置换环的元素分别为 \(x_1,x_2,\cdots,x_p\),分两种情况:

  • \(p\le 2\),我们就找出一个 \(y\) 使得 \(y\) 已经复位了——显然,由于 \(n\ge 2\),我们总能找出这样的 \(y\),那么我们就执行以下操作:

    • 交换 \(x_1,y\),当前局面为 \(-y,x_2,-x_1\)
    • 交换 \(x_1,x_2\)(原本 \(y,x_2\) 位置上的数),当前局面为 \(-y,x_1,-x_2\)
    • 交换 \(x_2,y\)(原本 \(y,x_1\) 位置上的数),当前局面为 \(x_2,x_1,y\)

    共使用了三次操作。

  • \(p>2\),那么考虑以下操作:

    • \(\forall i\in[2,p-1]\),交换 \(x_i,x_1\) 位置上的数,置换环依次变为:
      • \(x_1,x_2,x_3,x_4,\cdots,x_{p-1},x_p\)
      • \(-x_2,-x_1,x_3,x_4,\cdots,x_{p-1},x_p\)
      • \(-x_3,-x_1,x_2,x_4,\cdots,x_{p-1},x_p\)
      • \(-x_4,-x_1,x_2,x_3,\cdots,x_{p-1},x_p\)
      • ……
      • \(-x_{p-1},-x_1,x_2,x_3,\cdots,x_{p-2},x_p\)
    • 此时我们不能再交换 \(x_{p-1}\)\(x_p\) 了,因为那样会使 \(x_1,x_p\) 的操作次数的奇偶性发生错误,因此考虑特判最后三个元素,即执行以下操作:
      • 交换 \(x_1,x_p\),得到 \(-x_{p-1},-x_p,x_2,x_3,\cdots,x_{p-2},x_1\)
      • 交换 \(x_1,x_{p-1}\),得到 \(-x_1,-x_p,x_2,x_3,\cdots,x_{p-2},x_{p-1}\)
      • 交换 \(x_1,x_p\),得到 \(x_p,x_1,x_2,x_3,\cdots,x_{p-2},x_{p-1}\)

    共使用了 \(p+1\) 次操作。

这样即可实现本题要求,操作次数不超过 \(n+1\)

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
	#define FILE_SIZE 1<<23
	char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
	inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
	inline void putc(char x){(*p3++=x);}
	template<typename T> void read(T &x){
		x=0;char c=getchar();T neg=0;
		while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
		while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
		if(neg) x=(~x)+1;
	}
	template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
	template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
	void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=2e5;
int n,p[MAXN+5],pth_n;
bool vis[MAXN+5];
vector<int> pth[MAXN+5];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&p[i]);
	for(int i=1;i<=n;i++) if(!vis[i]&&p[i]!=i){
		int cur=p[i];pth[++pth_n].pb(i);vis[i]=1;
		while(cur!=i) pth[pth_n].pb(cur),vis[cur]=1,cur=p[cur];
	} vector<pii> ans;//printf("%d\n",pth_n);
	for(int i=1;i+1<=pth_n;i+=2){
		ans.pb(mp(pth[i][0],pth[i+1][0]));
		for(int j=1;j<pth[i].size();j++) ans.pb(mp(pth[i][j],pth[i+1][0]));
		for(int j=1;j<pth[i+1].size();j++) ans.pb(mp(pth[i+1][j],pth[i][0]));
		ans.pb(mp(pth[i][0],pth[i+1][0]));
	}
	if(pth_n&1){
		if(pth[pth_n].size()==2){
			for(int i=1;i<=n;i++){
				if((i^pth[pth_n][0])&&(i^pth[pth_n][1])){
					ans.pb(mp(i,pth[pth_n][0]));
					ans.pb(mp(i,pth[pth_n][1]));
					ans.pb(mp(i,pth[pth_n][0]));
					break;
				}
			}
		} else {
			for(int i=1;i+1<pth[pth_n].size();i++)
				ans.pb(mp(pth[pth_n][0],pth[pth_n][i]));
			ans.pb(mp(pth[pth_n][1],pth[pth_n].back()));
			ans.pb(mp(pth[pth_n][0],pth[pth_n].back()));
			ans.pb(mp(pth[pth_n][0],pth[pth_n][1]));
		}
	} printf("%d\n",ans.size());
	for(int i=0;i<ans.size();i++) printf("%d %d\n",ans[i].fi,ans[i].se);
	return 0;
}
posted @ 2021-03-18 09:19  tzc_wk  阅读(86)  评论(0)    收藏  举报