題意:
給你一個長度爲n的串,你每次可以選擇一個點i,然後將循環向右移位一次。讓你輸出選擇的點的次序使得最終的這個串遞增。你最多可以使用的操作次數不超過
題解:
這個的話,我以爲我想錯了,爲什麼會這麼簡單呢。
就從小到大枚舉每個位置,然後找到未排序的最小的點的最前面的位置,然後一次往前移兩格,直到當前位置或者當前位置+1的地方,如果是當前位置+1的地方的話,就再移兩次即可。
然後最後兩個數有可能是逆序的,但是不代表不能將他們正序,就像題目中樣例的最後一個。
所以我們只需要從後往前再做一次像上面那樣的操作即可。
最多的次數的話,應該是這麼算的:假設每次都會交換最多次,也就是n/2+1次,然後(首項+末項)*項數/2*2的話,大概就是
那麼很明顯在n>=3的情況下,它是不會超的。
時間複雜度
#include<bits/stdc++.h>
using namespace std;
const int N=505;
int a[N];
vector<int>ans;
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
ans.clear();
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int p=1;
while(p<=n-2){
int u=p;
for(int i=p+1;i<=n;i++)
if(a[i]<a[u])
u=i;
while(u-2>=p)
swap(a[u],a[u-2]),swap(a[u],a[u-1]),u-=2,ans.push_back(u);
if(u==p+1)
swap(a[u-1],a[u+1]),swap(a[u-1],a[u]),u--,ans.push_back(u),ans.push_back(u);
p++;
}
p=n;
while(p>=3){
int u=p;
for(int i=p-1;i;i--)
if(a[i]>a[u])
u=i;
while(u+2<=p)
swap(a[u],a[u+2]),swap(a[u],a[u+1]),u+=2,ans.push_back(u-2),ans.push_back(u-2);
if(u==p-1)
swap(a[u+1],a[u-1]),swap(a[u],a[u+1]),u++,ans.push_back(u-2);
p--;
}
int f=0;
for(int i=1;i<n;i++)
if(a[i]>a[i+1])
f=1;
if(f)
printf("-1\n");
else {
printf("%d\n",ans.size());
for(int i:ans)
printf("%d ",i);
printf("\n");
}
}
return 0;
}