CodeForces 612e Square Root of Permutation(置换+构造)

题意:给出一个1到n的序列,定义运算p[I] = q[q[I]],q为p的平方根,现在给出p,求出任意一个符合题意的q。

思路:将序列视为一个有向图,对于每个位置,将I和p[I]之间连一条边,可以发现,一个序列是由若干不相交的环组成的,而且对于平方运算,奇环长度不变,偶环分裂成两个小的环,所以可以将p中所有的环求出来。

对于奇环,认为他们原先是由奇环组成的,并求出原先的奇环

对于偶环,将两个长度相等的偶环合并,如果合并后还有剩余的偶环,则不存在平方根。

#include <bits/stdc++.h>
#define eps 1e-6
#define LL long long
#define pii pair<int, int>
#define pb push_back
#define mp make_pair
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

const int MAXN = 1000100;
//const int INF = 0x3f3f3f3f;
int n;
int a[MAXN];
int ans[MAXN];
bool vis[MAXN];
vector< vector<int> > cyc[MAXN];
bool check() {
	for (int i = 1; i <= n; i++) 
		if (!(i&1) && (cyc[i].size()&1))
			return false;
	return true;
}
void work() {
	for (int i = 1; i <= n; i++) {
		if (i&1) {
			for (int j = 0; j < cyc[i].size(); j++) {
				for (int k = 0; k < i; k++)
					ans[cyc[i][j][k]] = a[ cyc[i][j][(k+(i-1)/2)%i] ]; 
			}
		}
		else {
			for (int j = 0; j < cyc[i].size(); j+=2) {
				for (int k = 0; k < i; k++) {
					ans[cyc[i][j][k]] = a[ cyc[i][j+1][(i+k-1)%i] ];
					ans[cyc[i][j+1][k]] = a[ cyc[i][j][k] ];
				}
			}
		}
	}
}
int main()
{
	//freopen("input.txt", "r", stdin);
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) 
		scanf("%d", &a[i]);
	for (int i = 1; i <= n; i++) if (!vis[i]) {
		vector<int> tmp;
		int pos = i;
		do {
			vis[pos] = true;
			tmp.pb(pos);
			pos = a[pos];
		 } while (pos != i);
		 cyc[tmp.size()].pb(tmp);
	}
	if (!check()) puts("-1");
	else {
		work();
		for (int i = 1; i <= n; i++)
			printf("%d ", ans[i]);
	}
	return 0;
}
















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值