BNUOJ 26474 Bread Sorting

时间:2023-03-09 07:50:58
BNUOJ 26474 Bread Sorting
 /*给出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<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=;
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.num<b.num;
}
int lowbit(int x)
{
return x&(-x);
}
void updata(int i,int x)
{
while(i<=n)
{
c[i]+=x;
i=i+lowbit(i);
}
}
int sum(int x)
{
int ans=;
while(x>)
{
ans+=c[x];
x=x-lowbit(x);
}
return ans;
}
int main()
{
int i,j;
while(scanf("%d",&n)!=EOF)
{
memset(c,,sizeof(c));
for(i=;i<=n;i++)
{
scanf("%d",&p[i].num);
p[i].index=i;
}
sort(p+,p+n+,cmp);
for(i=;i<=n;i++)
b[p[i].index]=i; int ans1=,ans2=;
for(i=;i<=n;i++)
{
updata(b[i],);
ans1=ans1+(sum(n)-sum(b[i]));//sum(p[i])是前面比b[i]小的数的个数
}
memset(c,,sizeof(c));
memset(p,,sizeof(p));
memset(b,,sizeof(b));
for(i=;i<=n;i++)
{
scanf("%d",&p[i].num);
p[i].index=i;
}
sort(p+,p+n+,cmp);
for(i=;i<=n;i++)
b[p[i].index]=i; for(i=;i<=n;i++)
{
updata(b[i],);
ans2=ans2+(sum(n)-sum(b[i]));
}
printf("%d %d\n",ans1,ans2);
if(ans1%==ans2%) printf("Possible\n");
else printf("Impossible\n");
}
return ;
}
PS:这道题置换群也可以破
有奇数个有偶数个元素的轮换就是不可以
有偶数个有偶数个元素的轮换就是可以