题目描述
《基础物理实验》是一门精品好课,手残的 JJLeo 需要做 nn 个不同的实验,将其编号为 1,2,⋯,n1,2,⋯,n,它们的难度严格递增。
现在,智能化的选课网站帮他选择了一个做实验的顺序 [p1,p2,⋯,pn][p1,p2,⋯,pn],其中 pipi 表示第 ii 次做的实验的编号。因为每个实验只需要做一次,且所有实验都必须做,所以 [p1,p2,⋯,pn][p1,p2,⋯,pn] 中 11 到 nn 中每个整数都恰好出现了一次。
做实验应该循序渐进,因此 JJLeo 希望他做实验的难度可以严格递增,即满足 [p1,p2,⋯,pn]=[1,2,⋯,n][p1,p2,⋯,pn]=[1,2,⋯,n]。针对这种诉求,人性化的选课网站提供了一种更换实验顺序的方案,每个同学可以进行如下操作任意次:
- 选择一个正整数 ii 满足 1<i<n1<i<n 且 pi−1>pi>pi+1pi−1>pi>pi+1,将 [p1,⋯,pi−1,pi,pi+1,⋯,pn][p1,⋯,pi−1,pi,pi+1,⋯,pn] 更改为 [p1,⋯,pi+1,pi,pi−1,⋯,pn][p1,⋯,pi+1,pi,pi−1,⋯,pn]。
现在 JJLeo 想求助于你,能否进行合适的操作来更换实验顺序,实现他的目标;如果可以,最少需要多少次操作。
输入
第一行为数据组数 tt (1≤t≤1001≤t≤100)。
对于每组数据,第一行一个正整数 nn (3≤n≤10003≤n≤1000),表示 JJLeo 要做的物理实验的数量。
第二行 nn 个以空格分隔的正整数 pipi (1≤pi≤n1≤pi≤n),表示选课网站帮 JJLeo 选择的做实验的顺序 [p1,p2,⋯,pn][p1,p2,⋯,pn],保证 [p1,p2,⋯,pn][p1,p2,⋯,pn] 中 11 到 nn 中每个整数都恰好出现了一次。
输出
对于每组数据,输出一行,一个整数,如果该组数据可以通过合适的操作实现 JJLeo 的目标,输出最少需要操作的次数;否则,输出 −1−1。
输入样例
2 3 3 2 1 3 1 3 2
输出样例
1 -1
样例解释
对于第一组数据,选择 i=2i=2 并交换 p1p1 与 p3p3,序列变成 [1,2,3][1,2,3],只需一次操作即可满足要求。
对于第二组数据,无论如何选择 ii 进行操作,序列都无法变成 [1,2,3][1,2,3],故输出 −1−1。
AUTHOR:JJLeoc
#include <stdio.h> int main() { int t,a[1050],i,j,n,x=0,y=0,flag=0; scanf("%d",&t); while(t--) { flag=0; x=0; y=0; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d",&a[i]); if((a[i]-i)&1) flag=-1; } for(i=1;i<=n;i++) { for(j=1;j<i;j++) { if(a[j]>a[i]) x++; } } for(i=1;i<=n;i+=2) { for(j=1;j<i;j+=2) { if(a[j]>a[i]) y++; } } for(i=2;i<=n;i+=2) { for(j=2;j<i;j+=2) { if(a[j]>a[i]) y++; } } if(y*3==x&&flag==0) printf("%d\n",y); else printf("-1\n"); } return 0; }
考虑逆序对,总体的逆序对,每交换一次,整个序列的逆序对-3,奇数或偶数位上的逆序对-1,要使得,整个序列的逆序对为0 也就是,奇数和偶数位上的逆序对分别为0 ,那么整个数列的逆序对的三倍=奇数或偶数位上的逆序对,那么一定可以 交换到单增序列。以及,奇数位上偶数位上分别必须是奇数和偶数。
来源:oschina
链接:https://my.oschina.net/u/4717998/blog/4794344