http://www.bnuoj.com/bnuoj/problem_show.php?pid=26474
/*给出n个原始顺序的数,再给出要排成目标状态顺序,每次从第一个数列中选择三个,把这三个数中最右边的数放在最左边,然后其他两个数右
移一个单位,为你从原始状态能不能排序成目标状态。
本人YY的结论,从特殊到一般,虽然一般的只是手证了数值比较小的:结论应该就是1到n的n个数的全排列,分成相等的奇排序和偶排序,且个数一样,同个集合中的排列可以互相转换
比如1 2 3 4的全排1 2 3 4
1 4 2 3
1 3 4 2
4 1 3 2
4 2 1 3
4 3 2 1
2 4 3 1
2 1 4 3
2 3 1 4
3 4 1 2(可由4 1 3 2变成,一样的)
3 2 4 1
3 1 2 4
这个偶排序占了12个,其他十二个是奇排序
所以这道题直接比较两个数列的奇偶性
*/
#include
#include
#include
using namespace std;
const int maxn=100010;
int a[maxn],b[maxn],c[maxn];
int n;
struct point
{
int num,index;
}p[maxn];
int cmp(const point a,const point b)
{
return a.num0)
{
ans+=c[x];
x=x-lowbit(x);
}
return ans;
}
int main()
{
int i,j;
while(scanf("%d",&n)!=EOF)
{
memset(c,0,sizeof(c));
for(i=1;i<=n;i++)
{
scanf("%d",&p[i].num);
p[i].index=i;
}
sort(p+1,p+n+1,cmp);
for(i=1;i<=n;i++)
b[p[i].index]=i;
int ans1=0,ans2=0;
for(i=1;i<=n;i++)
{
updata(b[i],1);
ans1=ans1+(sum(n)-sum(b[i]));//sum(p[i])是前面比b[i]小的数的个数
}
memset(c,0,sizeof(c));
memset(p,0,sizeof(p));
memset(b,0,sizeof(b));
for(i=1;i<=n;i++)
{
scanf("%d",&p[i].num);
p[i].index=i;
}
sort(p+1,p+n+1,cmp);
for(i=1;i<=n;i++)
b[p[i].index]=i;
for(i=1;i<=n;i++)
{
updata(b[i],1);
ans2=ans2+(sum(n)-sum(b[i]));
}
printf("%d %d\n",ans1,ans2);
if(ans1%2==ans2%2) printf("Possible\n");
else printf("Impossible\n");
}
return 0;
}
PS:这道题置换群也可以破
有奇数个有偶数个元素的轮换就是不可以
有偶数个有偶数个元素的轮换就是可以