DeepDarkFantasy

从东京出发,不久便到一处驿站,写道:日暮里。  ——鲁迅《藤野先生》

定义一个置换的平方为对1~n的序列做两次该置换得到的序列。已知一个置换的平方,并且这个结果是一个排列,求该置换。

输入第一行一个数n表示排列长度,接下来一行n个数描述排列。

有解则输出一行n个数表示原排列。否则输出一行一个-1。

测试点编号

特征

0~1

n<=10

2~9

n<=1000000

【题解】

注:由于置换和排列在数学表现形式上是一样的,于是下文不对此进行详细区分。

首先对于任意一个排列,我们都可以将其看作一个有向图,即若排列中第i个点为x,那么相应的图中就会有一条从i连向x的边。那么对于一个置换的平方所得到的置换,相当于如果原图中有一条从x到y的边和一条从y到z的边,那么在新图中就会有一条从x到z的边。通过观察发现,原图中只有环的奇偶性会对答案的构成方式产生影响,于是我们可以对奇环和偶环分别进行讨论得到答案。

对于奇环的情况,可以令一个有5个点奇环为12345,那么在图中移动两步得到的图会是13524,那么如果中间有一个奇环的话,我们就可以按顺序遍历环的前一半和后一半得到原来的环。

对于偶环的情况,假设有一个偶环为123456,那么最终的结果会是形成两个环135与246,那么我们每次可以每次去两个环的同一位置上的数接在一起得到原来的环。

由于奇环所得到的答案一定是一个奇环,偶环得到的答案一定是两个长度相等的环,那么无解的情况就显然是新图中偶环的个数为奇数个。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<vector>
using namespace std;
#define MAXN 1000100
int n,len,a[MAXN],vis[MAXN],id[MAXN],ans[MAXN];
vector<int> c[MAXN];
inline int read()
{
int x=,f=; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-; ch=getchar();}
while(isdigit(ch)) {x=x*+ch-''; ch=getchar();}
return x*f;
}
bool cmp(int a,int b)
{return c[a].size()<c[b].size();}
void dfs(int x)
{
c[len].push_back(x);
vis[x]=;
if(!vis[a[x]]) dfs(a[x]);
}
int main()
{
freopen("deepdarkfantasy.in","r",stdin);
freopen("deepdarkfantasy.out","w",stdout);
n=read();
for(int i=;i<=n;i++) a[read()]=i;
for(int i=;i<=n;i++)
if(!vis[i]) {len++; dfs(i);}
for(int i=;i<=len;i++) id[i]=i;
sort(id+,id+len+,cmp);
for(int i=;i<=len;i++)
{
if(c[id[i]].size()&) //奇环
{
int mid=c[id[i]].size()>>;
mid++;
for(int j=;j<c[id[i]].size();j++)
ans[c[id[i]][j]]=c[id[i]][(j+mid)%c[id[i]].size()];
}
else //偶环
{
if(c[id[i]].size()!=c[id[i+]].size())
{
printf("-1\n");
return ;
}
else
{
for(int j=;j<c[id[i]].size();j++)
{
ans[c[id[i]][j]]=c[id[i+]][j];
ans[c[id[i+]][j]]=c[id[i]][(j+)%c[id[i]].size()];
}
i++;
}
}
}
for(int i=;i<=n;i++) printf("%d ",ans[i]);
printf("\n");
return ;
}

【NOI模拟赛(湖南)】DeepDarkFantasy的更多相关文章

  1. NOI模拟赛 Day1

    [考完试不想说话系列] 他们都会做呢QAQ 我毛线也不会呢QAQ 悲伤ING 考试问题: 1.感觉不是很清醒,有点困╯﹏╰ 2.为啥总不按照计划来!!! 3.脑洞在哪里 4.把模拟赛当作真正的比赛,紧 ...

  2. 6.28 NOI模拟赛 好题 状压dp 随机化

    算是一道比较新颖的题目 尽管好像是两年前的省选模拟赛题目.. 对于20%的分数 可以进行爆搜,对于另外20%的数据 因为k很小所以考虑上状压dp. 观察最后答案是一个连通块 从而可以发现这个连通块必然 ...

  3. NOI 模拟赛 #2

    得分非常惨惨,半个小时写的纯暴力 70 分竟然拿了 rank 1... 如果 OYJason 和 wxjor 在可能会被爆踩吧 嘤 T1 欧拉子图 给一个无向图,如果一个边集的导出子图是一个欧拉回路, ...

  4. 【2018.12.10】NOI模拟赛3

    题目 WZJ题解 大概就是全场就我写不过 $FFT$ 系列吧……自闭 T1 奶一口,下次再写不出这种 $NTT$ 裸题题目我就艹了自己 -_-||| 而且这跟我口胡的自创模拟题 $set1$ 的 $T ...

  5. NOI模拟赛Day5

    T1 有and,xor,or三种操作,每个人手中一个数,求和左边进行某一种运算的最大值,当t==2时,还需要求最大值的个数. test1 20% n<=1000 O(n^2)暴力 test2 2 ...

  6. NOI模拟赛Day4

    看到成绩的时候我的内心** woc第一题写错了呵呵呵呵呵呵呵呵 人不能太浪,会遭报应的** ------------------------------------------------------ ...

  7. NOI模拟赛Day3

    终于A题啦鼓掌~开心~ 开考看完题后,觉得第二题很好捏(傻叉上线 搞到十一点准备弃疗了然后突然发现我会做第一题 于是瞎码了码,就去准备饭票了... 好了,停止扯淡(就我一个我妹子每天不说话好难受QAQ ...

  8. NOI模拟赛Day2

    深深的感受到了自己的水 ---------------------------------------------------------------------------------------- ...

  9. NOI 模拟赛

    T1 Article 给 $m$ 个好串,定义一个字符串分割方案是好的当且仅当它分割出来的子串中"是好串的子串"的串长占原串串长超过 85%,定义一个好的分割方案的权值为这种分割方 ...

随机推荐

  1. Android计时器TimerTask,Timer,Handler

    Android计时器TimerTask,Timer,若要在TimerTask中更新主线程UI,鉴于Android编程模型不允许在非主线程中更新主线程UI,因此需要结合Android的Handler实现 ...

  2. (转)Android属性设置android:noHistory="true"

    设置 android:noHistory="true"后,该Activity在statck中不留历史痕迹.默认的值是false. 举例说明,假设有三个Activity分别是:A,B ...

  3. js实现选项卡功能

    1.css .liclick{ border: 1px black solid; background: #fff; float: left; width: 80px; height: 35px; l ...

  4. DevExpress LookUpEdit和ComboBoxEdit部分用法

    LookUpEdit 1.绑定列 (注意点:LookUpEdit1的FieldName要和绑定的列明一致) 方式一: LookUpEdit1.Properties.DisplayMember = &q ...

  5. 多分类问题multicalss classification

    多分类问题:有N个类别C1,C2,...,Cn,多分类学习的基本思路是"拆解法",即将多分类任务拆分为若干个而分类任务求解,最经典的拆分策略是:"一对一",&q ...

  6. SQL基础学习篇--字符函数

    字符函数可与SELECT,UPDATE,DELETE RIGHT()----从右侧开始选择  SELECT RIGHT(列,字符数量) FROM 表 LEFT()----从左侧开始选择  SUBSTR ...

  7. mif_maker2010.exe下载和使用说明

    mif_malker2010.exe下载地址:http://pan.baidu.com/s/1bCqAp4 使用说明:http://www.cnblogs.com/BitArt/archive/201 ...

  8. Hibernate从入门到精通(十)多对多单向关联映射

    上一篇文章Hibernate从入门到精通(九)一对多双向关联映射中我们讲解了一下关于一对多关联映射的相关内容,这次我们继续多对多单向关联映射. 多对多单向关联映射 在讲解多对多单向关联映射之前,首先看 ...

  9. 如何在Swing窗体增删组件后及时刷新显示新界面

    转自:http://blog.csdn.net/leeshuqing/article/details/8636211 关键的四行代码,连续调用窗体的四个方法即可: repaint();validate ...

  10. spring IOC源码分析(1)

    1.何谓Spring IOC 何谓Spring IOC?书上谓之“依赖注入”,那何谓“依赖注入”? 作为一个Java程序猿,应该遇到过这样的问题,当你在代码中需要使用某个类提供的功能时,你首先需要ne ...