有一天,Twilight Sparkle对如何对一系列序列进行排序感兴趣 整数a1,a2,...,a以非递减顺序排列。年轻 独角兽,她唯一可以进行的手术是单位轮班。那是, 她可以将序列的最后一个元素移动到它的开头:
a1,a2,...,a→an,a1,a2,..., - 1.帮助Twilight Sparkle to 计算:她需要的最小操作数是多少 排序顺序?
输入
第一行包含整数n(2≤n≤105)。第二 line包含n个整数a1,a2,...,an(1≤ai≤105)。输出
如果不能对序列输出-1进行排序。除此以外 输出Twilight Sparkle需要排序的最小操作次数 它。实例
输入
2
2 1
输出
1
输入
3
1 3 2
输出
-1
输入
2
1 2
输出
0
上面是问题,现在我感到困惑,因为那里的解决方案使用了一个名为“s”的变量并且出于某种原因在它周围播放但我不知道为什么使用该变量,如果有人能告诉我我'谢天谢地。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n, s, v(0);
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++) cin >> a[i];
for (int i = 0; i < n - 1; i++) if (a[i] > a[i + 1]) s = i, v++;
if (a[n - 1] > a[0]) s = n - 1, v++;
if (v == 0) cout << 0 << endl;
else if (v > 1) cout << -1 << endl;
else cout << n - 1 - s << endl;
return 0;
}
现在这里是我自己的解决方案,除了10 ^ 5(及其周围)大小的数组外,它的工作原理和所有内容,但是问题时间限制只有1000毫秒,并且由于嵌套循环使得它超出了限制超过O(10 ^ 8),在他们的系统上是1000毫秒。
#include <bits/stdc++.h>
#define fl(i,n) for(int i = 0; i < n; i++)
#define ll long long
#define nl endl
#define pb push_back
#define mp make_pair
#define PII pair<int,int>
#define EPS 1e-9
#define INF 1e9
using namespace std;
bool check(int a[], int n){
for(int i = 0; i < n-1; i++){
if(a[i] <= a[i+1]) continue;
return false;
}
return true;
}
int main()
{
int n;
cin >> n;
int a[n]; //is out of standard i know but it's accepted in the contest's compiler so we just use it
for(int i = 0; i < n; i++){
cin >> a[i];
}
if(check(a,n)){
cout << 0;
return 0;
}
int ret = 0;
for(int i = 0; i < n-1; i++){
ret++;
for(int j = n-1; j > 0; j--)
a[j] ^= a[j-1] ^= a[j] ^= a[j-1]; //is xor swap
if(check(a,n)){
cout << ret;
return 0;
}
}
cout << -1;
return 0;
}
PS:我跟踪了解决方案的代码,即使我得到了正确的答案,我也根本不知道它的含义。
答案 0 :(得分:2)
其他人的实现依赖于算法洞察力。如果序列由两个已经排序的部分组成,则可以通过向后移动来对序列进行排序的唯一方法。然后,目标是检查存在多少未分类的不连续性以及它们的位置。这是s
似乎用于:序列的(最后)不连续性的索引。 v
是不连续的数量。
如果有0,它已经排序了。如果超过1,则不合格。如果它只是一个,那么您可以轻松地计算出需要执行多少次移动以将不连续性拉回到前面,使用它在原始序列中的位置(s
)。
唯一额外的代码行是检查序列末尾的不连续性的特殊情况。
我的建议:生成一组更大的测试序列,并为每个测试序列打印v
和s
。